s4:rootdse LDB module - remove unused variable
[Samba/gebeck_regimport.git] / source3 / rpcclient / cmd_spoolss.c
blob1bb3a71d5e951e1864792028f375cb1a7ec8f416
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;
139 /****************************************************************************
140 ****************************************************************************/
142 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
143 TALLOC_CTX *mem_ctx,
144 int argc, const char **argv)
146 WERROR werror;
147 struct policy_handle hnd;
148 uint32_t access_mask = PRINTER_ALL_ACCESS;
149 NTSTATUS status;
150 struct spoolss_DevmodeContainer devmode_ctr;
152 ZERO_STRUCT(devmode_ctr);
154 if (argc < 2) {
155 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
156 return WERR_OK;
159 if (argc >= 3) {
160 sscanf(argv[2], "%x", &access_mask);
163 /* Open the printer handle */
165 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
166 argv[1],
167 NULL,
168 devmode_ctr,
169 access_mask,
170 &hnd,
171 &werror);
172 if (W_ERROR_IS_OK(werror)) {
173 printf("Printer %s opened successfully\n", argv[1]);
174 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
176 if (!W_ERROR_IS_OK(werror)) {
177 printf("Error closing printer handle! (%s)\n",
178 get_dos_error_msg(werror));
182 return werror;
185 /****************************************************************************
186 ****************************************************************************/
188 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
190 if (!r)
191 return;
193 printf("\tprintername:[%s]\n", r->printername);
194 printf("\tservername:[%s]\n", r->servername);
195 printf("\tcjobs:[0x%x]\n", r->cjobs);
196 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
197 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
198 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
199 r->time.day, r->time.day_of_week);
200 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
201 r->time.second, r->time.millisecond);
203 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
204 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
206 printf("\tversion:[0x%x]\n", r->version);
207 printf("\tfree_build:[0x%x]\n", r->free_build);
208 printf("\tspooling:[0x%x]\n", r->spooling);
209 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
210 printf("\tsession_counter:[0x%x]\n", r->session_counter);
211 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
212 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
213 printf("\tjob_error:[0x%x]\n", r->job_error);
214 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
215 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
216 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
217 printf("\tchange_id:[0x%x]\n", r->change_id);
218 printf("\tlast_error: %s\n", win_errstr(r->last_error));
219 printf("\tstatus:[0x%x]\n", r->status);
220 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
221 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
222 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
223 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
224 printf("\tref_ic:[0x%x]\n", r->ref_ic);
225 printf("\treserved2:[0x%x]\n", r->reserved2);
226 printf("\treserved3:[0x%x]\n", r->reserved3);
228 printf("\n");
231 /****************************************************************************
232 ****************************************************************************/
234 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
236 printf("\tflags:[0x%x]\n", r->flags);
237 printf("\tname:[%s]\n", r->name);
238 printf("\tdescription:[%s]\n", r->description);
239 printf("\tcomment:[%s]\n", r->comment);
241 printf("\n");
244 /****************************************************************************
245 ****************************************************************************/
247 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
249 printf("\tservername:[%s]\n", r->servername);
250 printf("\tprintername:[%s]\n", r->printername);
251 printf("\tsharename:[%s]\n", r->sharename);
252 printf("\tportname:[%s]\n", r->portname);
253 printf("\tdrivername:[%s]\n", r->drivername);
254 printf("\tcomment:[%s]\n", r->comment);
255 printf("\tlocation:[%s]\n", r->location);
256 printf("\tsepfile:[%s]\n", r->sepfile);
257 printf("\tprintprocessor:[%s]\n", r->printprocessor);
258 printf("\tdatatype:[%s]\n", r->datatype);
259 printf("\tparameters:[%s]\n", r->parameters);
260 printf("\tattributes:[0x%x]\n", r->attributes);
261 printf("\tpriority:[0x%x]\n", r->priority);
262 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
263 printf("\tstarttime:[0x%x]\n", r->starttime);
264 printf("\tuntiltime:[0x%x]\n", r->untiltime);
265 printf("\tstatus:[0x%x]\n", r->status);
266 printf("\tcjobs:[0x%x]\n", r->cjobs);
267 printf("\taverageppm:[0x%x]\n", r->averageppm);
269 if (r->secdesc)
270 display_sec_desc(r->secdesc);
272 printf("\n");
275 /****************************************************************************
276 ****************************************************************************/
278 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
280 display_sec_desc(r->secdesc);
282 printf("\n");
285 /****************************************************************************
286 ****************************************************************************/
288 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
290 printf("\tservername:[%s]\n", r->servername);
291 printf("\tprintername:[%s]\n", r->printername);
292 printf("\tattributes:[0x%x]\n", r->attributes);
293 printf("\n");
296 /****************************************************************************
297 ****************************************************************************/
299 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
301 printf("\tprintername:[%s]\n", r->printername);
302 printf("\tportname:[%s]\n", r->portname);
303 printf("\tattributes:[0x%x]\n", r->attributes);
304 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
305 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
306 printf("\n");
309 /****************************************************************************
310 ****************************************************************************/
312 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
314 printf("\tstatus:[0x%x]\n", r->status);
315 printf("\n");
318 /****************************************************************************
319 ****************************************************************************/
321 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
323 printf("\tguid:[%s]\n", r->guid);
324 printf("\taction:[0x%x]\n", r->action);
325 printf("\n");
328 /****************************************************************************
329 ****************************************************************************/
331 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
332 TALLOC_CTX *mem_ctx,
333 int argc, const char **argv)
335 WERROR result;
336 uint32_t level = 1;
337 union spoolss_PrinterInfo *info;
338 uint32_t i, count;
339 const char *name;
340 uint32_t flags = PRINTER_ENUM_LOCAL;
342 if (argc > 4) {
343 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
344 return WERR_OK;
347 if (argc >= 2) {
348 level = atoi(argv[1]);
351 if (argc >= 3) {
352 name = argv[2];
353 } else {
354 name = cli->srv_name_slash;
357 if (argc == 4) {
358 flags = atoi(argv[3]);
361 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
362 flags,
363 name,
364 level,
366 &count,
367 &info);
368 if (W_ERROR_IS_OK(result)) {
370 if (!count) {
371 printf ("No printers returned.\n");
372 goto done;
375 for (i = 0; i < count; i++) {
376 switch (level) {
377 case 0:
378 display_print_info0(&info[i].info0);
379 break;
380 case 1:
381 display_print_info1(&info[i].info1);
382 break;
383 case 2:
384 display_print_info2(&info[i].info2);
385 break;
386 case 3:
387 display_print_info3(&info[i].info3);
388 break;
389 case 4:
390 display_print_info4(&info[i].info4);
391 break;
392 case 5:
393 display_print_info5(&info[i].info5);
394 break;
395 case 6:
396 display_print_info6(&info[i].info6);
397 break;
398 default:
399 printf("unknown info level %d\n", level);
400 goto done;
404 done:
406 return result;
409 /****************************************************************************
410 ****************************************************************************/
412 static void display_port_info_1(struct spoolss_PortInfo1 *r)
414 printf("\tPort Name:\t[%s]\n", r->port_name);
417 /****************************************************************************
418 ****************************************************************************/
420 static void display_port_info_2(struct spoolss_PortInfo2 *r)
422 printf("\tPort Name:\t[%s]\n", r->port_name);
423 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
424 printf("\tDescription:\t[%s]\n", r->description);
425 printf("\tPort Type:\t" );
426 if (r->port_type) {
427 int comma = 0; /* hack */
428 printf( "[" );
429 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
430 printf( "Read" );
431 comma = 1;
433 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
434 printf( "%sWrite", comma ? ", " : "" );
435 comma = 1;
437 /* These two have slightly different interpretations
438 on 95/98/ME but I'm disregarding that for now */
439 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
440 printf( "%sRedirected", comma ? ", " : "" );
441 comma = 1;
443 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
444 printf( "%sNet-Attached", comma ? ", " : "" );
446 printf( "]\n" );
447 } else {
448 printf( "[Unset]\n" );
450 printf("\tReserved:\t[%d]\n", r->reserved);
451 printf("\n");
454 /****************************************************************************
455 ****************************************************************************/
457 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
458 TALLOC_CTX *mem_ctx, int argc,
459 const char **argv)
461 WERROR result;
462 uint32_t level = 1;
463 uint32_t count;
464 union spoolss_PortInfo *info;
466 if (argc > 2) {
467 printf("Usage: %s [level]\n", argv[0]);
468 return WERR_OK;
471 if (argc == 2) {
472 level = atoi(argv[1]);
475 /* Enumerate ports */
477 result = rpccli_spoolss_enumports(cli, mem_ctx,
478 cli->srv_name_slash,
479 level,
481 &count,
482 &info);
483 if (W_ERROR_IS_OK(result)) {
484 int i;
486 for (i = 0; i < count; i++) {
487 switch (level) {
488 case 1:
489 display_port_info_1(&info[i].info1);
490 break;
491 case 2:
492 display_port_info_2(&info[i].info2);
493 break;
494 default:
495 printf("unknown info level %d\n", level);
496 break;
501 return result;
504 /****************************************************************************
505 ****************************************************************************/
507 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
508 TALLOC_CTX *mem_ctx,
509 int argc, const char **argv)
511 struct policy_handle pol;
512 WERROR result;
513 NTSTATUS status;
514 uint32_t info_level = 2;
515 union spoolss_PrinterInfo info;
516 struct spoolss_SetPrinterInfoCtr info_ctr;
517 struct spoolss_SetPrinterInfo2 info2;
518 const char *printername, *comment = NULL;
519 struct spoolss_DevmodeContainer devmode_ctr;
520 struct sec_desc_buf secdesc_ctr;
522 if (argc == 1 || argc > 3) {
523 printf("Usage: %s printername comment\n", argv[0]);
525 return WERR_OK;
528 /* Open a printer handle */
529 if (argc == 3) {
530 comment = argv[2];
533 ZERO_STRUCT(devmode_ctr);
534 ZERO_STRUCT(secdesc_ctr);
536 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
538 /* get a printer handle */
539 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
540 printername,
541 PRINTER_ALL_ACCESS,
542 &pol);
543 if (!W_ERROR_IS_OK(result))
544 goto done;
546 /* Get printer info */
547 result = rpccli_spoolss_getprinter(cli, mem_ctx,
548 &pol,
549 info_level,
551 &info);
552 if (!W_ERROR_IS_OK(result))
553 goto done;
556 /* Modify the comment. */
557 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
558 info2.comment = comment;
560 info_ctr.level = 2;
561 info_ctr.info.info2 = &info2;
563 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
564 &pol,
565 &info_ctr,
566 &devmode_ctr,
567 &secdesc_ctr,
568 0, /* command */
569 &result);
570 if (W_ERROR_IS_OK(result))
571 printf("Success in setting comment.\n");
573 done:
574 if (is_valid_policy_hnd(&pol))
575 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
577 return result;
580 /****************************************************************************
581 ****************************************************************************/
583 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
584 TALLOC_CTX *mem_ctx,
585 int argc, const char **argv)
587 struct policy_handle pol;
588 WERROR result;
589 NTSTATUS status;
590 uint32_t info_level = 2;
591 union spoolss_PrinterInfo info;
592 const char *printername,
593 *new_printername = NULL;
594 struct spoolss_SetPrinterInfoCtr info_ctr;
595 struct spoolss_SetPrinterInfo2 info2;
596 struct spoolss_DevmodeContainer devmode_ctr;
597 struct sec_desc_buf secdesc_ctr;
599 ZERO_STRUCT(devmode_ctr);
600 ZERO_STRUCT(secdesc_ctr);
602 if (argc == 1 || argc > 3) {
603 printf("Usage: %s printername new_printername\n", argv[0]);
605 return WERR_OK;
608 /* Open a printer handle */
609 if (argc == 3) {
610 new_printername = argv[2];
613 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
615 /* get a printer handle */
616 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
617 printername,
618 PRINTER_ALL_ACCESS,
619 &pol);
620 if (!W_ERROR_IS_OK(result))
621 goto done;
623 /* Get printer info */
624 result = rpccli_spoolss_getprinter(cli, mem_ctx,
625 &pol,
626 info_level,
628 &info);
629 if (!W_ERROR_IS_OK(result))
630 goto done;
632 /* Modify the printername. */
633 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
634 info2.printername = new_printername;
636 info_ctr.level = 2;
637 info_ctr.info.info2 = &info2;
639 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
640 &pol,
641 &info_ctr,
642 &devmode_ctr,
643 &secdesc_ctr,
644 0, /* command */
645 &result);
646 if (W_ERROR_IS_OK(result))
647 printf("Success in setting printername.\n");
649 done:
650 if (is_valid_policy_hnd(&pol))
651 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
653 return result;
656 /****************************************************************************
657 ****************************************************************************/
659 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
660 TALLOC_CTX *mem_ctx,
661 int argc, const char **argv)
663 struct policy_handle pol;
664 WERROR result;
665 uint32_t level = 1;
666 const char *printername;
667 union spoolss_PrinterInfo info;
669 if (argc == 1 || argc > 3) {
670 printf("Usage: %s <printername> [level]\n", argv[0]);
671 return WERR_OK;
674 /* Open a printer handle */
675 if (argc == 3) {
676 level = atoi(argv[2]);
679 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
681 /* get a printer handle */
683 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
684 printername,
685 SEC_FLAG_MAXIMUM_ALLOWED,
686 &pol);
687 if (!W_ERROR_IS_OK(result)) {
688 goto done;
691 /* Get printer info */
693 result = rpccli_spoolss_getprinter(cli, mem_ctx,
694 &pol,
695 level,
697 &info);
698 if (!W_ERROR_IS_OK(result)) {
699 goto done;
702 /* Display printer info */
703 switch (level) {
704 case 0:
705 display_print_info0(&info.info0);
706 break;
707 case 1:
708 display_print_info1(&info.info1);
709 break;
710 case 2:
711 display_print_info2(&info.info2);
712 break;
713 case 3:
714 display_print_info3(&info.info3);
715 break;
716 case 4:
717 display_print_info4(&info.info4);
718 break;
719 case 5:
720 display_print_info5(&info.info5);
721 break;
722 case 6:
723 display_print_info6(&info.info6);
724 break;
725 case 7:
726 display_print_info7(&info.info7);
727 break;
728 default:
729 printf("unknown info level %d\n", level);
730 break;
732 done:
733 if (is_valid_policy_hnd(&pol)) {
734 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
737 return result;
740 /****************************************************************************
741 ****************************************************************************/
743 static void display_reg_value(struct regval_blob *value)
745 const char *text = NULL;
746 DATA_BLOB blob;
748 switch(regval_type(value)) {
749 case REG_DWORD:
750 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
751 *((uint32_t *) regval_data_p(value)));
752 break;
753 case REG_SZ:
754 blob = data_blob_const(regval_data_p(value), regval_size(value));
755 pull_reg_sz(talloc_tos(), &blob, &text);
756 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
757 break;
758 case REG_BINARY: {
759 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
760 size_t i, len;
761 printf("%s: REG_BINARY:", regval_name(value));
762 len = strlen(hex);
763 for (i=0; i<len; i++) {
764 if (hex[i] == '\0') {
765 break;
767 if (i%40 == 0) {
768 putchar('\n');
770 putchar(hex[i]);
772 TALLOC_FREE(hex);
773 putchar('\n');
774 break;
776 case REG_MULTI_SZ: {
777 uint32_t i;
778 const char **values;
779 blob = data_blob_const(regval_data_p(value), regval_size(value));
781 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
782 d_printf("pull_reg_multi_sz failed\n");
783 break;
786 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
787 for (i=0; values[i] != NULL; i++) {
788 d_printf("%s\n", values[i]);
790 TALLOC_FREE(values);
791 break;
793 default:
794 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
799 /****************************************************************************
800 ****************************************************************************/
802 static void display_printer_data(const char *v,
803 enum winreg_Type type,
804 uint8_t *data,
805 uint32_t length)
807 int i;
808 union spoolss_PrinterData r;
809 DATA_BLOB blob = data_blob_const(data, length);
810 WERROR result;
812 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
813 if (!W_ERROR_IS_OK(result)) {
814 return;
817 switch (type) {
818 case REG_DWORD:
819 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
820 break;
821 case REG_SZ:
822 printf("%s: REG_SZ: %s\n", v, r.string);
823 break;
824 case REG_BINARY: {
825 char *hex = hex_encode_talloc(NULL,
826 r.binary.data, r.binary.length);
827 size_t len;
828 printf("%s: REG_BINARY:", v);
829 len = strlen(hex);
830 for (i=0; i<len; i++) {
831 if (hex[i] == '\0') {
832 break;
834 if (i%40 == 0) {
835 putchar('\n');
837 putchar(hex[i]);
839 TALLOC_FREE(hex);
840 putchar('\n');
841 break;
843 case REG_MULTI_SZ:
844 printf("%s: REG_MULTI_SZ: ", v);
845 for (i=0; r.string_array[i] != NULL; i++) {
846 printf("%s ", r.string_array[i]);
848 printf("\n");
849 break;
850 default:
851 printf("%s: unknown type 0x%02x:\n", v, type);
852 break;
856 /****************************************************************************
857 ****************************************************************************/
859 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
860 TALLOC_CTX *mem_ctx,
861 int argc, const char **argv)
863 struct policy_handle pol;
864 WERROR result;
865 fstring printername;
866 const char *valuename;
867 enum winreg_Type type;
868 uint8_t *data;
869 uint32_t needed;
871 if (argc != 3) {
872 printf("Usage: %s <printername> <valuename>\n", argv[0]);
873 printf("<printername> of . queries print server\n");
874 return WERR_OK;
876 valuename = argv[2];
878 /* Open a printer handle */
880 if (strncmp(argv[1], ".", sizeof(".")) == 0)
881 fstrcpy(printername, cli->srv_name_slash);
882 else
883 slprintf(printername, sizeof(printername)-1, "%s\\%s",
884 cli->srv_name_slash, argv[1]);
886 /* get a printer handle */
888 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
889 printername,
890 SEC_FLAG_MAXIMUM_ALLOWED,
891 &pol);
892 if (!W_ERROR_IS_OK(result))
893 goto done;
895 /* Get printer info */
897 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
898 &pol,
899 valuename,
901 &type,
902 &needed,
903 &data);
904 if (!W_ERROR_IS_OK(result))
905 goto done;
907 /* Display printer data */
909 display_printer_data(valuename, type, data, needed);
911 done:
912 if (is_valid_policy_hnd(&pol))
913 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
915 return result;
918 /****************************************************************************
919 ****************************************************************************/
921 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
922 TALLOC_CTX *mem_ctx,
923 int argc, const char **argv)
925 struct policy_handle pol;
926 WERROR result;
927 NTSTATUS status;
928 fstring printername;
929 const char *valuename, *keyname;
931 enum winreg_Type type;
932 uint8_t *data = NULL;
933 uint32_t offered = 0;
934 uint32_t needed;
936 if (argc != 4) {
937 printf("Usage: %s <printername> <keyname> <valuename>\n",
938 argv[0]);
939 printf("<printername> of . queries print server\n");
940 return WERR_OK;
942 valuename = argv[3];
943 keyname = argv[2];
945 /* Open a printer handle */
947 if (strncmp(argv[1], ".", sizeof(".")) == 0)
948 fstrcpy(printername, cli->srv_name_slash);
949 else
950 slprintf(printername, sizeof(printername)-1, "%s\\%s",
951 cli->srv_name_slash, argv[1]);
953 /* get a printer handle */
955 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
956 printername,
957 SEC_FLAG_MAXIMUM_ALLOWED,
958 &pol);
959 if (!W_ERROR_IS_OK(result))
960 goto done;
962 /* Get printer info */
964 data = talloc_zero_array(mem_ctx, uint8_t, offered);
965 if (!data) {
966 goto done;
969 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
970 &pol,
971 keyname,
972 valuename,
973 &type,
974 data,
975 offered,
976 &needed,
977 &result);
978 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
979 offered = needed;
980 data = talloc_zero_array(mem_ctx, uint8_t, offered);
981 if (!data) {
982 goto done;
984 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
985 &pol,
986 keyname,
987 valuename,
988 &type,
989 data,
990 offered,
991 &needed,
992 &result);
995 if (!NT_STATUS_IS_OK(status)) {
996 goto done;
999 if (!W_ERROR_IS_OK(result))
1000 goto done;
1002 /* Display printer data */
1004 display_printer_data(valuename, type, data, needed);
1007 done:
1008 if (is_valid_policy_hnd(&pol))
1009 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1011 return result;
1014 /****************************************************************************
1015 ****************************************************************************/
1017 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1019 if (!r) {
1020 return;
1023 printf("Printer Driver Info 1:\n");
1024 printf("\tDriver Name: [%s]\n", r->driver_name);
1025 printf("\n");
1028 /****************************************************************************
1029 ****************************************************************************/
1031 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1033 if (!r) {
1034 return;
1037 printf("Printer Driver Info 2:\n");
1038 printf("\tVersion: [%x]\n", r->version);
1039 printf("\tDriver Name: [%s]\n", r->driver_name);
1040 printf("\tArchitecture: [%s]\n", r->architecture);
1041 printf("\tDriver Path: [%s]\n", r->driver_path);
1042 printf("\tDatafile: [%s]\n", r->data_file);
1043 printf("\tConfigfile: [%s]\n", r->config_file);
1044 printf("\n");
1047 /****************************************************************************
1048 ****************************************************************************/
1050 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1052 int i;
1054 if (!r) {
1055 return;
1058 printf("Printer Driver Info 3:\n");
1059 printf("\tVersion: [%x]\n", r->version);
1060 printf("\tDriver Name: [%s]\n", r->driver_name);
1061 printf("\tArchitecture: [%s]\n", r->architecture);
1062 printf("\tDriver Path: [%s]\n", r->driver_path);
1063 printf("\tDatafile: [%s]\n", r->data_file);
1064 printf("\tConfigfile: [%s]\n", r->config_file);
1065 printf("\tHelpfile: [%s]\n", r->help_file);
1067 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1068 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1071 printf("\tMonitorname: [%s]\n", r->monitor_name);
1072 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1073 printf("\n");
1076 /****************************************************************************
1077 ****************************************************************************/
1079 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1081 int i;
1083 if (!r) {
1084 return;
1087 printf("Printer Driver Info 4:\n");
1088 printf("\tVersion: [%x]\n", r->version);
1089 printf("\tDriver Name: [%s]\n", r->driver_name);
1090 printf("\tArchitecture: [%s]\n", r->architecture);
1091 printf("\tDriver Path: [%s]\n", r->driver_path);
1092 printf("\tDatafile: [%s]\n", r->data_file);
1093 printf("\tConfigfile: [%s]\n", r->config_file);
1094 printf("\tHelpfile: [%s]\n", r->help_file);
1096 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1097 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1100 printf("\tMonitorname: [%s]\n", r->monitor_name);
1101 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1103 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1104 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1106 printf("\n");
1109 /****************************************************************************
1110 ****************************************************************************/
1112 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1114 if (!r) {
1115 return;
1118 printf("Printer Driver Info 5:\n");
1119 printf("\tVersion: [%x]\n", r->version);
1120 printf("\tDriver Name: [%s]\n", r->driver_name);
1121 printf("\tArchitecture: [%s]\n", r->architecture);
1122 printf("\tDriver Path: [%s]\n", r->driver_path);
1123 printf("\tDatafile: [%s]\n", r->data_file);
1124 printf("\tConfigfile: [%s]\n", r->config_file);
1125 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1126 printf("\tConfig Version: [0x%x]\n", r->config_version);
1127 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1128 printf("\n");
1131 /****************************************************************************
1132 ****************************************************************************/
1134 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1136 int i;
1138 if (!r) {
1139 return;
1142 printf("Printer Driver Info 6:\n");
1143 printf("\tVersion: [%x]\n", r->version);
1144 printf("\tDriver Name: [%s]\n", r->driver_name);
1145 printf("\tArchitecture: [%s]\n", r->architecture);
1146 printf("\tDriver Path: [%s]\n", r->driver_path);
1147 printf("\tDatafile: [%s]\n", r->data_file);
1148 printf("\tConfigfile: [%s]\n", r->config_file);
1149 printf("\tHelpfile: [%s]\n", r->help_file);
1151 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1152 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1155 printf("\tMonitorname: [%s]\n", r->monitor_name);
1156 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1158 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1159 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1162 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1163 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1164 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1165 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1166 printf("\tHardware ID: [%s]\n", r->hardware_id);
1167 printf("\tProvider: [%s]\n", r->provider);
1169 printf("\n");
1172 /****************************************************************************
1173 ****************************************************************************/
1175 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1177 int i;
1179 if (!r) {
1180 return;
1183 printf("Printer Driver Info 8:\n");
1184 printf("\tVersion: [%x]\n", r->version);
1185 printf("\tDriver Name: [%s]\n", r->driver_name);
1186 printf("\tArchitecture: [%s]\n", r->architecture);
1187 printf("\tDriver Path: [%s]\n", r->driver_path);
1188 printf("\tDatafile: [%s]\n", r->data_file);
1189 printf("\tConfigfile: [%s]\n", r->config_file);
1190 printf("\tHelpfile: [%s]\n", r->help_file);
1191 printf("\tMonitorname: [%s]\n", r->monitor_name);
1192 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1194 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1195 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1198 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1199 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1202 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1203 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1204 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1205 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1206 printf("\tHardware ID: [%s]\n", r->hardware_id);
1207 printf("\tProvider: [%s]\n", r->provider);
1208 printf("\tPrint Processor: [%s]\n", r->print_processor);
1209 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1210 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1211 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1213 printf("\tInf Path: [%s]\n", r->inf_path);
1214 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1215 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1216 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1218 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1219 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1220 (long long unsigned int)r->min_inbox_driver_ver_version);
1222 printf("\n");
1225 /****************************************************************************
1226 ****************************************************************************/
1228 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1229 TALLOC_CTX *mem_ctx,
1230 int argc, const char **argv)
1232 struct policy_handle pol;
1233 WERROR werror;
1234 uint32_t level = 3;
1235 const char *printername;
1236 uint32_t i;
1237 bool success = false;
1238 union spoolss_DriverInfo info;
1239 uint32_t server_major_version;
1240 uint32_t server_minor_version;
1242 if ((argc == 1) || (argc > 3)) {
1243 printf("Usage: %s <printername> [level]\n", argv[0]);
1244 return WERR_OK;
1247 /* get the arguments need to open the printer handle */
1249 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1251 if (argc == 3) {
1252 level = atoi(argv[2]);
1255 /* Open a printer handle */
1257 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1258 printername,
1259 PRINTER_ACCESS_USE,
1260 &pol);
1261 if (!W_ERROR_IS_OK(werror)) {
1262 printf("Error opening printer handle for %s!\n", printername);
1263 return werror;
1266 /* loop through and print driver info level for each architecture */
1268 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1270 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1271 &pol,
1272 archi_table[i].long_archi,
1273 level,
1274 0, /* offered */
1275 archi_table[i].version,
1277 &info,
1278 &server_major_version,
1279 &server_minor_version);
1280 if (!W_ERROR_IS_OK(werror)) {
1281 continue;
1284 /* need at least one success */
1286 success = true;
1288 printf("\n[%s]\n", archi_table[i].long_archi);
1290 switch (level) {
1291 case 1:
1292 display_print_driver1(&info.info1);
1293 break;
1294 case 2:
1295 display_print_driver2(&info.info2);
1296 break;
1297 case 3:
1298 display_print_driver3(&info.info3);
1299 break;
1300 case 4:
1301 display_print_driver4(&info.info4);
1302 break;
1303 case 5:
1304 display_print_driver5(&info.info5);
1305 break;
1306 case 6:
1307 display_print_driver6(&info.info6);
1308 break;
1309 case 8:
1310 display_print_driver8(&info.info8);
1311 break;
1312 default:
1313 printf("unknown info level %d\n", level);
1314 break;
1318 /* Cleanup */
1320 if (is_valid_policy_hnd(&pol)) {
1321 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1324 if (success) {
1325 werror = WERR_OK;
1328 return werror;
1331 /****************************************************************************
1332 ****************************************************************************/
1334 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1335 TALLOC_CTX *mem_ctx,
1336 const char *architecture,
1337 uint32_t level)
1339 WERROR werror;
1340 uint32_t count = 0;
1341 union spoolss_DriverInfo *info = NULL;
1342 uint32_t j;
1344 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1345 cli->srv_name_slash,
1346 architecture,
1347 level,
1349 &count,
1350 &info);
1352 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1353 printf("Server does not support environment [%s]\n",
1354 architecture);
1355 return WERR_OK;
1358 if (count == 0) {
1359 return WERR_OK;
1362 if (!W_ERROR_IS_OK(werror)) {
1363 printf("Error getting driver for environment [%s] - %s\n",
1364 architecture, win_errstr(werror));
1365 return werror;
1368 printf("\n[%s]\n", architecture);
1370 switch (level) {
1371 case 1:
1372 for (j=0; j < count; j++) {
1373 display_print_driver1(&info[j].info1);
1375 break;
1376 case 2:
1377 for (j=0; j < count; j++) {
1378 display_print_driver2(&info[j].info2);
1380 break;
1381 case 3:
1382 for (j=0; j < count; j++) {
1383 display_print_driver3(&info[j].info3);
1385 break;
1386 case 4:
1387 for (j=0; j < count; j++) {
1388 display_print_driver4(&info[j].info4);
1390 break;
1391 case 5:
1392 for (j=0; j < count; j++) {
1393 display_print_driver5(&info[j].info5);
1395 break;
1396 case 6:
1397 for (j=0; j < count; j++) {
1398 display_print_driver6(&info[j].info6);
1400 break;
1401 case 8:
1402 for (j=0; j < count; j++) {
1403 display_print_driver8(&info[j].info8);
1405 break;
1406 default:
1407 printf("unknown info level %d\n", level);
1408 return WERR_UNKNOWN_LEVEL;
1411 return werror;
1414 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1415 TALLOC_CTX *mem_ctx,
1416 int argc, const char **argv)
1418 WERROR werror = WERR_OK;
1419 uint32_t level = 1;
1420 uint32_t i;
1421 const char *architecture = NULL;
1423 if (argc > 3) {
1424 printf("Usage: enumdrivers [level] [architecture]\n");
1425 return WERR_OK;
1428 if (argc >= 2) {
1429 level = atoi(argv[1]);
1432 if (argc == 3) {
1433 architecture = argv[2];
1436 if (architecture) {
1437 return enum_driver_by_architecture(cli, mem_ctx,
1438 architecture,
1439 level);
1442 /* loop through and print driver info level for each architecture */
1443 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1444 /* check to see if we already asked for this architecture string */
1446 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1447 continue;
1450 werror = enum_driver_by_architecture(cli, mem_ctx,
1451 archi_table[i].long_archi,
1452 level);
1453 if (!W_ERROR_IS_OK(werror)) {
1454 break;
1458 return werror;
1461 /****************************************************************************
1462 ****************************************************************************/
1464 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1466 printf("\tDirectory Name:[%s]\n", r->directory_name);
1469 /****************************************************************************
1470 ****************************************************************************/
1472 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1473 TALLOC_CTX *mem_ctx,
1474 int argc, const char **argv)
1476 WERROR result;
1477 NTSTATUS status;
1478 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1479 DATA_BLOB buffer;
1480 uint32_t offered;
1481 union spoolss_DriverDirectoryInfo info;
1482 uint32_t needed;
1484 if (argc > 2) {
1485 printf("Usage: %s [environment]\n", argv[0]);
1486 return WERR_OK;
1489 /* Get the arguments need to open the printer handle */
1491 if (argc == 2) {
1492 env = argv[1];
1495 /* Get the directory. Only use Info level 1 */
1497 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1498 cli->srv_name_slash,
1499 env,
1501 NULL, /* buffer */
1502 0, /* offered */
1503 NULL, /* info */
1504 &needed,
1505 &result);
1506 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1507 offered = needed;
1508 buffer = data_blob_talloc_zero(mem_ctx, needed);
1510 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1511 cli->srv_name_slash,
1512 env,
1514 &buffer,
1515 offered,
1516 &info,
1517 &needed,
1518 &result);
1521 if (W_ERROR_IS_OK(result)) {
1522 display_printdriverdir_1(&info.info1);
1525 return result;
1528 /****************************************************************************
1529 ****************************************************************************/
1531 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1532 struct spoolss_AddDriverInfo3 *info,
1533 const char *arch)
1536 int i;
1538 for (i=0; archi_table[i].long_archi != NULL; i++)
1540 if (strcmp(arch, archi_table[i].short_archi) == 0)
1542 info->version = archi_table[i].version;
1543 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1544 break;
1548 if (archi_table[i].long_archi == NULL)
1550 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1553 return;
1557 /**************************************************************************
1558 wrapper for strtok to get the next parameter from a delimited list.
1559 Needed to handle the empty parameter string denoted by "NULL"
1560 *************************************************************************/
1562 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1563 const char *delim, const char **dest,
1564 char **saveptr)
1566 char *ptr;
1568 /* get the next token */
1569 ptr = strtok_r(str, delim, saveptr);
1571 /* a string of 'NULL' is used to represent an empty
1572 parameter because two consecutive delimiters
1573 will not return an empty string. See man strtok(3)
1574 for details */
1575 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1576 ptr = NULL;
1579 if (dest != NULL) {
1580 *dest = talloc_strdup(mem_ctx, ptr);
1583 return ptr;
1586 /********************************************************************************
1587 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1588 string in the form of
1589 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1590 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1591 <Default Data Type>:<Comma Separated list of Files>
1592 *******************************************************************************/
1594 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1595 char *args)
1597 char *str, *str2;
1598 int count = 0;
1599 char *saveptr = NULL;
1600 struct spoolss_StringArray *deps;
1601 const char **file_array = NULL;
1602 int i;
1604 /* fill in the UNISTR fields */
1605 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1606 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1607 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1608 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1609 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1610 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1611 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1613 /* <Comma Separated List of Dependent Files> */
1614 /* save the beginning of the string */
1615 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1616 str = str2;
1618 /* begin to strip out each filename */
1619 str = strtok_r(str, ",", &saveptr);
1621 /* no dependent files, we are done */
1622 if (!str) {
1623 return true;
1626 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1627 if (!deps) {
1628 return false;
1631 while (str != NULL) {
1632 add_string_to_array(deps, str, &file_array, &count);
1633 str = strtok_r(NULL, ",", &saveptr);
1636 deps->string = talloc_zero_array(deps, const char *, count + 1);
1637 if (!deps->string) {
1638 return false;
1641 for (i=0; i < count; i++) {
1642 deps->string[i] = file_array[i];
1645 r->dependent_files = deps;
1647 return true;
1650 /****************************************************************************
1651 ****************************************************************************/
1653 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1654 TALLOC_CTX *mem_ctx,
1655 int argc, const char **argv)
1657 WERROR result;
1658 NTSTATUS status;
1659 uint32_t level = 3;
1660 struct spoolss_AddDriverInfoCtr info_ctr;
1661 struct spoolss_AddDriverInfo3 info3;
1662 const char *arch;
1663 char *driver_args;
1665 /* parse the command arguments */
1666 if (argc != 3 && argc != 4)
1668 printf ("Usage: %s <Environment> \\\n", argv[0]);
1669 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1670 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1671 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1672 printf ("\t[version]\n");
1674 return WERR_OK;
1677 /* Fill in the spoolss_AddDriverInfo3 struct */
1678 ZERO_STRUCT(info3);
1680 arch = cmd_spoolss_get_short_archi(argv[1]);
1681 if (!arch) {
1682 printf ("Error Unknown architechture [%s]\n", argv[1]);
1683 return WERR_INVALID_PARAM;
1686 set_drv_info_3_env(mem_ctx, &info3, arch);
1688 driver_args = talloc_strdup( mem_ctx, argv[2] );
1689 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1691 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1692 return WERR_INVALID_PARAM;
1695 /* if printer driver version specified, override the default version
1696 * used by the architecture. This allows installation of Windows
1697 * 2000 (version 3) printer drivers. */
1698 if (argc == 4)
1700 info3.version = atoi(argv[3]);
1704 info_ctr.level = level;
1705 info_ctr.info.info3 = &info3;
1707 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1708 cli->srv_name_slash,
1709 &info_ctr,
1710 &result);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return ntstatus_to_werror(status);
1714 if (W_ERROR_IS_OK(result)) {
1715 printf ("Printer Driver %s successfully installed.\n",
1716 info3.driver_name);
1719 return result;
1723 /****************************************************************************
1724 ****************************************************************************/
1726 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1727 TALLOC_CTX *mem_ctx,
1728 int argc, const char **argv)
1730 WERROR result;
1731 struct spoolss_SetPrinterInfoCtr info_ctr;
1732 struct spoolss_SetPrinterInfo2 info2;
1734 /* parse the command arguments */
1735 if (argc != 5)
1737 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1738 return WERR_OK;
1741 /* Fill in the DRIVER_INFO_2 struct */
1742 ZERO_STRUCT(info2);
1744 info2.printername = argv[1];
1745 info2.drivername = argv[3];
1746 info2.sharename = argv[2];
1747 info2.portname = argv[4];
1748 info2.comment = "Created by rpcclient";
1749 info2.printprocessor = "winprint";
1750 info2.datatype = "RAW";
1751 info2.devmode_ptr = 0;
1752 info2.secdesc_ptr = 0;
1753 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1754 info2.priority = 0;
1755 info2.defaultpriority = 0;
1756 info2.starttime = 0;
1757 info2.untiltime = 0;
1759 /* These three fields must not be used by AddPrinter()
1760 as defined in the MS Platform SDK documentation..
1761 --jerry
1762 info2.status = 0;
1763 info2.cjobs = 0;
1764 info2.averageppm = 0;
1767 info_ctr.level = 2;
1768 info_ctr.info.info2 = &info2;
1770 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1771 &info_ctr);
1772 if (W_ERROR_IS_OK(result))
1773 printf ("Printer %s successfully installed.\n", argv[1]);
1775 return result;
1778 /****************************************************************************
1779 ****************************************************************************/
1781 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1782 TALLOC_CTX *mem_ctx,
1783 int argc, const char **argv)
1785 struct policy_handle pol;
1786 WERROR result;
1787 NTSTATUS status;
1788 uint32_t level = 2;
1789 const char *printername;
1790 union spoolss_PrinterInfo info;
1791 struct spoolss_SetPrinterInfoCtr info_ctr;
1792 struct spoolss_SetPrinterInfo2 info2;
1793 struct spoolss_DevmodeContainer devmode_ctr;
1794 struct sec_desc_buf secdesc_ctr;
1796 ZERO_STRUCT(devmode_ctr);
1797 ZERO_STRUCT(secdesc_ctr);
1799 /* parse the command arguments */
1800 if (argc != 3)
1802 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1803 return WERR_OK;
1806 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1808 /* Get a printer handle */
1810 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1811 printername,
1812 PRINTER_ALL_ACCESS,
1813 &pol);
1814 if (!W_ERROR_IS_OK(result))
1815 goto done;
1817 /* Get printer info */
1819 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1820 &pol,
1821 level,
1823 &info);
1824 if (!W_ERROR_IS_OK(result)) {
1825 printf ("Unable to retrieve printer information!\n");
1826 goto done;
1829 /* Set the printer driver */
1831 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1832 info2.drivername = argv[2];
1834 info_ctr.level = 2;
1835 info_ctr.info.info2 = &info2;
1837 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1838 &pol,
1839 &info_ctr,
1840 &devmode_ctr,
1841 &secdesc_ctr,
1842 0, /* command */
1843 &result);
1844 if (!W_ERROR_IS_OK(result)) {
1845 printf("SetPrinter call failed!\n");
1846 goto done;;
1849 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1851 done:
1852 /* Cleanup */
1854 if (is_valid_policy_hnd(&pol))
1855 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1857 return result;
1861 /****************************************************************************
1862 ****************************************************************************/
1864 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1865 TALLOC_CTX *mem_ctx,
1866 int argc, const char **argv)
1868 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1869 NTSTATUS status;
1871 int i;
1872 int vers = -1;
1874 const char *arch = NULL;
1875 uint32_t delete_flags = 0;
1877 /* parse the command arguments */
1878 if (argc < 2 || argc > 4) {
1879 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1880 return WERR_OK;
1883 if (argc >= 3)
1884 arch = argv[2];
1885 if (argc == 4)
1886 vers = atoi (argv[3]);
1888 if (vers >= 0) {
1889 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1892 /* delete the driver for all architectures */
1893 for (i=0; archi_table[i].long_archi; i++) {
1895 if (arch && !strequal( archi_table[i].long_archi, arch))
1896 continue;
1898 if (vers >= 0 && archi_table[i].version != vers)
1899 continue;
1901 /* make the call to remove the driver */
1902 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1903 cli->srv_name_slash,
1904 archi_table[i].long_archi,
1905 argv[1],
1906 delete_flags,
1907 archi_table[i].version,
1908 &result);
1910 if ( !W_ERROR_IS_OK(result) )
1912 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1913 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1914 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1917 else
1919 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1920 archi_table[i].long_archi, archi_table[i].version);
1921 ret = WERR_OK;
1925 return ret;
1929 /****************************************************************************
1930 ****************************************************************************/
1932 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1933 TALLOC_CTX *mem_ctx,
1934 int argc, const char **argv)
1936 WERROR result = WERR_OK;
1937 NTSTATUS status;
1938 int i;
1940 /* parse the command arguments */
1941 if (argc != 2) {
1942 printf ("Usage: %s <driver>\n", argv[0]);
1943 return WERR_OK;
1946 /* delete the driver for all architectures */
1947 for (i=0; archi_table[i].long_archi; i++) {
1948 /* make the call to remove the driver */
1949 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1950 cli->srv_name_slash,
1951 archi_table[i].long_archi,
1952 argv[1],
1953 &result);
1954 if (!NT_STATUS_IS_OK(status)) {
1955 return result;
1957 if ( !W_ERROR_IS_OK(result) ) {
1958 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1959 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1960 argv[1], archi_table[i].long_archi,
1961 W_ERROR_V(result));
1963 } else {
1964 printf ("Driver %s removed for arch [%s].\n", argv[1],
1965 archi_table[i].long_archi);
1969 return result;
1972 /****************************************************************************
1973 ****************************************************************************/
1975 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1976 TALLOC_CTX *mem_ctx,
1977 int argc, const char **argv)
1979 WERROR result;
1980 NTSTATUS status;
1981 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1982 DATA_BLOB buffer;
1983 uint32_t offered;
1984 union spoolss_PrintProcessorDirectoryInfo info;
1985 uint32_t needed;
1987 /* parse the command arguments */
1988 if (argc > 2) {
1989 printf ("Usage: %s [environment]\n", argv[0]);
1990 return WERR_OK;
1993 if (argc == 2) {
1994 environment = argv[1];
1997 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1998 cli->srv_name_slash,
1999 environment,
2001 NULL, /* buffer */
2002 0, /* offered */
2003 NULL, /* info */
2004 &needed,
2005 &result);
2006 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2007 offered = needed;
2008 buffer = data_blob_talloc_zero(mem_ctx, needed);
2010 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2011 cli->srv_name_slash,
2012 environment,
2014 &buffer,
2015 offered,
2016 &info,
2017 &needed,
2018 &result);
2021 if (W_ERROR_IS_OK(result)) {
2022 printf("%s\n", info.info1.directory_name);
2025 return result;
2028 /****************************************************************************
2029 ****************************************************************************/
2031 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2032 int argc, const char **argv)
2034 struct policy_handle handle;
2035 WERROR werror;
2036 NTSTATUS status;
2037 const char *printername;
2038 union spoolss_AddFormInfo info;
2039 struct spoolss_AddFormInfo1 info1;
2040 struct spoolss_AddFormInfo2 info2;
2041 uint32_t level = 1;
2043 /* Parse the command arguments */
2045 if (argc < 3 || argc > 5) {
2046 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2047 return WERR_OK;
2050 /* Get a printer handle */
2052 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2054 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2055 printername,
2056 PRINTER_ALL_ACCESS,
2057 &handle);
2058 if (!W_ERROR_IS_OK(werror))
2059 goto done;
2061 /* Dummy up some values for the form data */
2063 if (argc == 4) {
2064 level = atoi(argv[3]);
2067 switch (level) {
2068 case 1:
2069 info1.flags = SPOOLSS_FORM_USER;
2070 info1.form_name = argv[2];
2071 info1.size.width = 100;
2072 info1.size.height = 100;
2073 info1.area.left = 0;
2074 info1.area.top = 10;
2075 info1.area.right = 20;
2076 info1.area.bottom = 30;
2078 info.info1 = &info1;
2080 break;
2081 case 2:
2082 info2.flags = SPOOLSS_FORM_USER;
2083 info2.form_name = argv[2];
2084 info2.size.width = 100;
2085 info2.size.height = 100;
2086 info2.area.left = 0;
2087 info2.area.top = 10;
2088 info2.area.right = 20;
2089 info2.area.bottom = 30;
2090 info2.keyword = argv[2];
2091 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2092 info2.mui_dll = NULL;
2093 info2.ressource_id = 0;
2094 info2.display_name = argv[2];
2095 info2.lang_id = 0;
2097 info.info2 = &info2;
2099 break;
2102 /* Add the form */
2105 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2106 &handle,
2107 level,
2108 info,
2109 &werror);
2111 done:
2112 if (is_valid_policy_hnd(&handle))
2113 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2115 return werror;
2118 /****************************************************************************
2119 ****************************************************************************/
2121 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2122 int argc, const char **argv)
2124 struct policy_handle handle;
2125 WERROR werror;
2126 NTSTATUS status;
2127 const char *printername;
2128 union spoolss_AddFormInfo info;
2129 struct spoolss_AddFormInfo1 info1;
2131 /* Parse the command arguments */
2133 if (argc != 3) {
2134 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2135 return WERR_OK;
2138 /* Get a printer handle */
2140 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2142 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2143 printername,
2144 SEC_FLAG_MAXIMUM_ALLOWED,
2145 &handle);
2146 if (!W_ERROR_IS_OK(werror))
2147 goto done;
2149 /* Dummy up some values for the form data */
2151 info1.flags = SPOOLSS_FORM_PRINTER;
2152 info1.size.width = 100;
2153 info1.size.height = 100;
2154 info1.area.left = 0;
2155 info1.area.top = 1000;
2156 info1.area.right = 2000;
2157 info1.area.bottom = 3000;
2158 info1.form_name = argv[2];
2160 info.info1 = &info1;
2162 /* Set the form */
2164 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2165 &handle,
2166 argv[2],
2168 info,
2169 &werror);
2171 done:
2172 if (is_valid_policy_hnd(&handle))
2173 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2175 return werror;
2178 /****************************************************************************
2179 ****************************************************************************/
2181 static const char *get_form_flag(int form_flag)
2183 switch (form_flag) {
2184 case SPOOLSS_FORM_USER:
2185 return "FORM_USER";
2186 case SPOOLSS_FORM_BUILTIN:
2187 return "FORM_BUILTIN";
2188 case SPOOLSS_FORM_PRINTER:
2189 return "FORM_PRINTER";
2190 default:
2191 return "unknown";
2195 /****************************************************************************
2196 ****************************************************************************/
2198 static void display_form_info1(struct spoolss_FormInfo1 *r)
2200 printf("%s\n" \
2201 "\tflag: %s (%d)\n" \
2202 "\twidth: %d, length: %d\n" \
2203 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2204 r->form_name, get_form_flag(r->flags), r->flags,
2205 r->size.width, r->size.height,
2206 r->area.left, r->area.right,
2207 r->area.top, r->area.bottom);
2210 /****************************************************************************
2211 ****************************************************************************/
2213 static void display_form_info2(struct spoolss_FormInfo2 *r)
2215 printf("%s\n" \
2216 "\tflag: %s (%d)\n" \
2217 "\twidth: %d, length: %d\n" \
2218 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2219 r->form_name, get_form_flag(r->flags), r->flags,
2220 r->size.width, r->size.height,
2221 r->area.left, r->area.right,
2222 r->area.top, r->area.bottom);
2223 printf("\tkeyword: %s\n", r->keyword);
2224 printf("\tstring_type: 0x%08x\n", r->string_type);
2225 printf("\tmui_dll: %s\n", r->mui_dll);
2226 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2227 printf("\tdisplay_name: %s\n", r->display_name);
2228 printf("\tlang_id: %d\n", r->lang_id);
2229 printf("\n");
2232 /****************************************************************************
2233 ****************************************************************************/
2235 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2236 int argc, const char **argv)
2238 struct policy_handle handle;
2239 WERROR werror;
2240 NTSTATUS status;
2241 const char *printername;
2242 DATA_BLOB buffer;
2243 uint32_t offered = 0;
2244 union spoolss_FormInfo info;
2245 uint32_t needed;
2246 uint32_t level = 1;
2248 /* Parse the command arguments */
2250 if (argc < 3 || argc > 5) {
2251 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2252 return WERR_OK;
2255 /* Get a printer handle */
2257 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2259 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2260 printername,
2261 SEC_FLAG_MAXIMUM_ALLOWED,
2262 &handle);
2263 if (!W_ERROR_IS_OK(werror))
2264 goto done;
2266 if (argc == 4) {
2267 level = atoi(argv[3]);
2270 /* Get the form */
2272 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2273 &handle,
2274 argv[2],
2275 level,
2276 NULL,
2277 offered,
2278 &info,
2279 &needed,
2280 &werror);
2281 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2282 buffer = data_blob_talloc_zero(mem_ctx, needed);
2283 offered = needed;
2284 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2285 &handle,
2286 argv[2],
2287 level,
2288 &buffer,
2289 offered,
2290 &info,
2291 &needed,
2292 &werror);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 return werror;
2299 switch (level) {
2300 case 1:
2301 display_form_info1(&info.info1);
2302 break;
2303 case 2:
2304 display_form_info2(&info.info2);
2305 break;
2308 done:
2309 if (is_valid_policy_hnd(&handle))
2310 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2312 return werror;
2315 /****************************************************************************
2316 ****************************************************************************/
2318 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2319 TALLOC_CTX *mem_ctx, int argc,
2320 const char **argv)
2322 struct policy_handle handle;
2323 WERROR werror;
2324 NTSTATUS status;
2325 const char *printername;
2327 /* Parse the command arguments */
2329 if (argc != 3) {
2330 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2331 return WERR_OK;
2334 /* Get a printer handle */
2336 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2338 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2339 printername,
2340 SEC_FLAG_MAXIMUM_ALLOWED,
2341 &handle);
2342 if (!W_ERROR_IS_OK(werror))
2343 goto done;
2345 /* Delete the form */
2347 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2348 &handle,
2349 argv[2],
2350 &werror);
2351 if (!NT_STATUS_IS_OK(status)) {
2352 return ntstatus_to_werror(status);
2355 done:
2356 if (is_valid_policy_hnd(&handle))
2357 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2359 return werror;
2362 /****************************************************************************
2363 ****************************************************************************/
2365 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2366 TALLOC_CTX *mem_ctx, int argc,
2367 const char **argv)
2369 struct policy_handle handle;
2370 WERROR werror;
2371 const char *printername;
2372 uint32_t num_forms, level = 1, i;
2373 union spoolss_FormInfo *forms;
2375 /* Parse the command arguments */
2377 if (argc < 2 || argc > 4) {
2378 printf ("Usage: %s <printer> [level]\n", argv[0]);
2379 return WERR_OK;
2382 /* Get a printer handle */
2384 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2386 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2387 printername,
2388 SEC_FLAG_MAXIMUM_ALLOWED,
2389 &handle);
2390 if (!W_ERROR_IS_OK(werror))
2391 goto done;
2393 if (argc == 3) {
2394 level = atoi(argv[2]);
2397 /* Enumerate forms */
2399 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2400 &handle,
2401 level,
2403 &num_forms,
2404 &forms);
2406 if (!W_ERROR_IS_OK(werror))
2407 goto done;
2409 /* Display output */
2411 for (i = 0; i < num_forms; i++) {
2412 switch (level) {
2413 case 1:
2414 display_form_info1(&forms[i].info1);
2415 break;
2416 case 2:
2417 display_form_info2(&forms[i].info2);
2418 break;
2422 done:
2423 if (is_valid_policy_hnd(&handle))
2424 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2426 return werror;
2429 /****************************************************************************
2430 ****************************************************************************/
2432 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2433 TALLOC_CTX *mem_ctx,
2434 int argc, const char **argv)
2436 WERROR result;
2437 NTSTATUS status;
2438 const char *printername;
2439 struct policy_handle pol;
2440 union spoolss_PrinterInfo info;
2441 enum winreg_Type type;
2442 union spoolss_PrinterData data;
2443 DATA_BLOB blob;
2445 /* parse the command arguments */
2446 if (argc < 5) {
2447 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2448 " <value> <data>\n",
2449 argv[0]);
2450 return WERR_OK;
2453 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2455 type = REG_NONE;
2457 if (strequal(argv[2], "string")) {
2458 type = REG_SZ;
2461 if (strequal(argv[2], "binary")) {
2462 type = REG_BINARY;
2465 if (strequal(argv[2], "dword")) {
2466 type = REG_DWORD;
2469 if (strequal(argv[2], "multistring")) {
2470 type = REG_MULTI_SZ;
2473 if (type == REG_NONE) {
2474 printf("Unknown data type: %s\n", argv[2]);
2475 result = WERR_INVALID_PARAM;
2476 goto done;
2479 /* get a printer handle */
2481 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2482 printername,
2483 SEC_FLAG_MAXIMUM_ALLOWED,
2484 &pol);
2485 if (!W_ERROR_IS_OK(result)) {
2486 goto done;
2489 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2490 &pol,
2493 &info);
2494 if (!W_ERROR_IS_OK(result)) {
2495 goto done;
2498 printf("%s\n", current_timestring(mem_ctx, true));
2499 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2501 /* Set the printer data */
2503 switch (type) {
2504 case REG_SZ:
2505 data.string = talloc_strdup(mem_ctx, argv[4]);
2506 W_ERROR_HAVE_NO_MEMORY(data.string);
2507 break;
2508 case REG_DWORD:
2509 data.value = strtoul(argv[4], NULL, 10);
2510 break;
2511 case REG_BINARY:
2512 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2513 break;
2514 case REG_MULTI_SZ: {
2515 int i, num_strings;
2516 const char **strings = NULL;
2518 for (i=4; i<argc; i++) {
2519 if (strcmp(argv[i], "NULL") == 0) {
2520 argv[i] = "";
2522 if (!add_string_to_array(mem_ctx, argv[i],
2523 &strings,
2524 &num_strings)) {
2525 result = WERR_NOMEM;
2526 goto done;
2529 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2530 if (!data.string_array) {
2531 result = WERR_NOMEM;
2532 goto done;
2534 for (i=0; i < num_strings; i++) {
2535 data.string_array[i] = strings[i];
2537 break;
2539 default:
2540 printf("Unknown data type: %s\n", argv[2]);
2541 result = WERR_INVALID_PARAM;
2542 goto done;
2545 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2546 if (!W_ERROR_IS_OK(result)) {
2547 goto done;
2550 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2551 &pol,
2552 argv[3], /* value_name */
2553 type,
2554 blob.data,
2555 blob.length,
2556 &result);
2557 if (!W_ERROR_IS_OK(result)) {
2558 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2559 goto done;
2561 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2563 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2564 &pol,
2567 &info);
2568 if (!W_ERROR_IS_OK(result)) {
2569 goto done;
2572 printf("%s\n", current_timestring(mem_ctx, true));
2573 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2575 done:
2576 /* cleanup */
2577 if (is_valid_policy_hnd(&pol)) {
2578 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2581 return result;
2584 /****************************************************************************
2585 ****************************************************************************/
2587 static void display_job_info1(struct spoolss_JobInfo1 *r)
2589 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2590 r->user_name, r->document_name, r->text_status, r->pages_printed,
2591 r->total_pages);
2594 /****************************************************************************
2595 ****************************************************************************/
2597 static void display_job_info2(struct spoolss_JobInfo2 *r)
2599 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2600 r->position, r->job_id,
2601 r->user_name, r->document_name, r->text_status, r->pages_printed,
2602 r->total_pages, r->size);
2605 /****************************************************************************
2606 ****************************************************************************/
2608 static void display_job_info3(struct spoolss_JobInfo3 *r)
2610 printf("jobid[%d], next_jobid[%d]\n",
2611 r->job_id, r->next_job_id);
2614 /****************************************************************************
2615 ****************************************************************************/
2617 static void display_job_info4(struct spoolss_JobInfo4 *r)
2619 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2620 r->position, r->job_id,
2621 r->user_name, r->document_name, r->text_status, r->pages_printed,
2622 r->total_pages, r->size, r->size_high);
2625 /****************************************************************************
2626 ****************************************************************************/
2628 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2629 TALLOC_CTX *mem_ctx, int argc,
2630 const char **argv)
2632 WERROR result;
2633 uint32_t level = 1, count, i;
2634 const char *printername;
2635 struct policy_handle hnd;
2636 union spoolss_JobInfo *info;
2638 if (argc < 2 || argc > 3) {
2639 printf("Usage: %s printername [level]\n", argv[0]);
2640 return WERR_OK;
2643 if (argc == 3) {
2644 level = atoi(argv[2]);
2647 /* Open printer handle */
2649 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2651 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2652 printername,
2653 SEC_FLAG_MAXIMUM_ALLOWED,
2654 &hnd);
2655 if (!W_ERROR_IS_OK(result))
2656 goto done;
2658 /* Enumerate ports */
2660 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2661 &hnd,
2662 0, /* firstjob */
2663 1000, /* numjobs */
2664 level,
2666 &count,
2667 &info);
2668 if (!W_ERROR_IS_OK(result)) {
2669 goto done;
2672 for (i = 0; i < count; i++) {
2673 switch (level) {
2674 case 1:
2675 display_job_info1(&info[i].info1);
2676 break;
2677 case 2:
2678 display_job_info2(&info[i].info2);
2679 break;
2680 default:
2681 d_printf("unknown info level %d\n", level);
2682 break;
2686 done:
2687 if (is_valid_policy_hnd(&hnd)) {
2688 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2691 return result;
2694 /****************************************************************************
2695 ****************************************************************************/
2697 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2698 TALLOC_CTX *mem_ctx, int argc,
2699 const char **argv)
2701 WERROR result;
2702 const char *printername;
2703 struct policy_handle hnd;
2704 uint32_t job_id;
2705 uint32_t level = 1;
2706 union spoolss_JobInfo info;
2708 if (argc < 3 || argc > 4) {
2709 printf("Usage: %s printername job_id [level]\n", argv[0]);
2710 return WERR_OK;
2713 job_id = atoi(argv[2]);
2715 if (argc == 4) {
2716 level = atoi(argv[3]);
2719 /* Open printer handle */
2721 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2723 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2724 printername,
2725 SEC_FLAG_MAXIMUM_ALLOWED,
2726 &hnd);
2727 if (!W_ERROR_IS_OK(result)) {
2728 goto done;
2731 /* Enumerate ports */
2733 result = rpccli_spoolss_getjob(cli, mem_ctx,
2734 &hnd,
2735 job_id,
2736 level,
2738 &info);
2740 if (!W_ERROR_IS_OK(result)) {
2741 goto done;
2744 switch (level) {
2745 case 1:
2746 display_job_info1(&info.info1);
2747 break;
2748 case 2:
2749 display_job_info2(&info.info2);
2750 break;
2751 case 3:
2752 display_job_info3(&info.info3);
2753 break;
2754 case 4:
2755 display_job_info4(&info.info4);
2756 break;
2757 default:
2758 d_printf("unknown info level %d\n", level);
2759 break;
2762 done:
2763 if (is_valid_policy_hnd(&hnd)) {
2764 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2767 return result;
2770 /****************************************************************************
2771 ****************************************************************************/
2773 static struct {
2774 const char *name;
2775 enum spoolss_JobControl val;
2776 } cmdvals[] = {
2777 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2778 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2779 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2780 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2781 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2782 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2783 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2784 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2785 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2788 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2790 int i;
2792 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2793 if (strequal(cmdvals[i].name, cmd)) {
2794 return cmdvals[i].val;
2797 return (enum spoolss_JobControl)atoi(cmd);
2800 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2801 TALLOC_CTX *mem_ctx, int argc,
2802 const char **argv)
2804 WERROR result;
2805 NTSTATUS status;
2806 const char *printername;
2807 struct policy_handle hnd;
2808 uint32_t job_id;
2809 enum spoolss_JobControl command;
2811 if (argc != 4) {
2812 printf("Usage: %s printername job_id command\n", argv[0]);
2813 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2814 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2815 return WERR_OK;
2818 job_id = atoi(argv[2]);
2819 command = parse_setjob_command(argv[3]);
2821 /* Open printer handle */
2823 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2825 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2826 printername,
2827 SEC_FLAG_MAXIMUM_ALLOWED,
2828 &hnd);
2829 if (!W_ERROR_IS_OK(result)) {
2830 goto done;
2833 /* Set Job */
2835 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2836 &hnd,
2837 job_id,
2838 NULL,
2839 command,
2840 &result);
2842 if (!W_ERROR_IS_OK(result)) {
2843 goto done;
2846 done:
2847 if (is_valid_policy_hnd(&hnd)) {
2848 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2851 return result;
2854 /****************************************************************************
2855 ****************************************************************************/
2857 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2858 TALLOC_CTX *mem_ctx, int argc,
2859 const char **argv)
2861 WERROR result;
2862 NTSTATUS status;
2863 uint32_t i = 0;
2864 const char *printername;
2865 struct policy_handle hnd;
2866 uint32_t value_offered = 0;
2867 const char *value_name = NULL;
2868 uint32_t value_needed;
2869 enum winreg_Type type;
2870 uint8_t *data = NULL;
2871 uint32_t data_offered = 0;
2872 uint32_t data_needed;
2874 if (argc != 2) {
2875 printf("Usage: %s printername\n", argv[0]);
2876 return WERR_OK;
2879 /* Open printer handle */
2881 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2883 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2884 printername,
2885 SEC_FLAG_MAXIMUM_ALLOWED,
2886 &hnd);
2887 if (!W_ERROR_IS_OK(result)) {
2888 goto done;
2891 /* Enumerate data */
2893 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2894 &hnd,
2896 value_name,
2897 value_offered,
2898 &value_needed,
2899 &type,
2900 data,
2901 data_offered,
2902 &data_needed,
2903 &result);
2905 if (!NT_STATUS_IS_OK(status)) {
2906 result = ntstatus_to_werror(status);
2907 goto done;
2910 if (!W_ERROR_IS_OK(result)) {
2911 goto done;
2914 data_offered = data_needed;
2915 value_offered = value_needed;
2916 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2917 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2919 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2921 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2922 &hnd,
2923 i++,
2924 value_name,
2925 value_offered,
2926 &value_needed,
2927 &type,
2928 data,
2929 data_offered,
2930 &data_needed,
2931 &result);
2932 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2933 struct regval_blob *v;
2935 v = regval_compose(talloc_tos(),
2936 value_name,
2937 type,
2938 data,
2939 data_offered);
2940 if (v == NULL) {
2941 result = WERR_NOMEM;
2942 goto done;
2945 display_reg_value(v);
2946 talloc_free(v);
2950 if (W_ERROR_V(result) == ERRnomoreitems) {
2951 result = W_ERROR(ERRsuccess);
2954 done:
2955 if (is_valid_policy_hnd(&hnd)) {
2956 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2959 return result;
2962 /****************************************************************************
2963 ****************************************************************************/
2965 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2966 TALLOC_CTX *mem_ctx, int argc,
2967 const char **argv)
2969 WERROR result;
2970 uint32_t i;
2971 const char *printername;
2972 struct policy_handle hnd;
2973 uint32_t count;
2974 struct spoolss_PrinterEnumValues *info;
2976 if (argc != 3) {
2977 printf("Usage: %s printername <keyname>\n", argv[0]);
2978 return WERR_OK;
2981 /* Open printer handle */
2983 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2985 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2986 printername,
2987 SEC_FLAG_MAXIMUM_ALLOWED,
2988 &hnd);
2989 if (!W_ERROR_IS_OK(result)) {
2990 goto done;
2993 /* Enumerate subkeys */
2995 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2996 &hnd,
2997 argv[2],
2999 &count,
3000 &info);
3001 if (!W_ERROR_IS_OK(result)) {
3002 goto done;
3005 for (i=0; i < count; i++) {
3006 display_printer_data(info[i].value_name,
3007 info[i].type,
3008 info[i].data->data,
3009 info[i].data->length);
3012 done:
3013 if (is_valid_policy_hnd(&hnd)) {
3014 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3017 return result;
3020 /****************************************************************************
3021 ****************************************************************************/
3023 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3024 TALLOC_CTX *mem_ctx, int argc,
3025 const char **argv)
3027 WERROR result;
3028 const char *printername;
3029 const char *keyname = NULL;
3030 struct policy_handle hnd;
3031 const char **key_buffer = NULL;
3032 int i;
3033 uint32_t offered = 0;
3035 if (argc < 2 || argc > 4) {
3036 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3037 return WERR_OK;
3040 if (argc >= 3) {
3041 keyname = argv[2];
3042 } else {
3043 keyname = "";
3046 if (argc == 4) {
3047 offered = atoi(argv[3]);
3050 /* Open printer handle */
3052 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3054 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3055 printername,
3056 SEC_FLAG_MAXIMUM_ALLOWED,
3057 &hnd);
3058 if (!W_ERROR_IS_OK(result)) {
3059 goto done;
3062 /* Enumerate subkeys */
3064 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3065 &hnd,
3066 keyname,
3067 &key_buffer,
3068 offered);
3070 if (!W_ERROR_IS_OK(result)) {
3071 goto done;
3074 for (i=0; key_buffer && key_buffer[i]; i++) {
3075 printf("%s\n", key_buffer[i]);
3078 done:
3080 if (is_valid_policy_hnd(&hnd)) {
3081 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3084 return result;
3087 /****************************************************************************
3088 ****************************************************************************/
3090 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3091 TALLOC_CTX *mem_ctx, int argc,
3092 const char **argv)
3094 const char *printername;
3095 const char *clientname;
3096 struct policy_handle hnd;
3097 WERROR result;
3098 NTSTATUS status;
3099 struct spoolss_NotifyOption option;
3101 if (argc != 2) {
3102 printf("Usage: %s printername\n", argv[0]);
3103 result = WERR_OK;
3104 goto done;
3107 /* Open printer */
3109 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3111 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3112 printername,
3113 SEC_FLAG_MAXIMUM_ALLOWED,
3114 &hnd);
3115 if (!W_ERROR_IS_OK(result)) {
3116 printf("Error opening %s\n", argv[1]);
3117 goto done;
3120 /* Create spool options */
3122 option.version = 2;
3123 option.count = 2;
3125 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3126 if (option.types == NULL) {
3127 result = WERR_NOMEM;
3128 goto done;
3131 option.types[0].type = PRINTER_NOTIFY_TYPE;
3132 option.types[0].count = 1;
3133 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3134 if (option.types[0].fields == NULL) {
3135 result = WERR_NOMEM;
3136 goto done;
3138 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3140 option.types[1].type = JOB_NOTIFY_TYPE;
3141 option.types[1].count = 1;
3142 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3143 if (option.types[1].fields == NULL) {
3144 result = WERR_NOMEM;
3145 goto done;
3147 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3149 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3150 if (!clientname) {
3151 result = WERR_NOMEM;
3152 goto done;
3155 /* Send rffpcnex */
3157 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3158 &hnd,
3161 clientname,
3162 123,
3163 &option,
3164 &result);
3165 if (!W_ERROR_IS_OK(result)) {
3166 printf("Error rffpcnex %s\n", argv[1]);
3167 goto done;
3170 done:
3171 if (is_valid_policy_hnd(&hnd))
3172 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3174 return result;
3177 /****************************************************************************
3178 ****************************************************************************/
3180 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3181 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3183 union spoolss_PrinterInfo info1, info2;
3184 WERROR werror;
3185 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3187 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3188 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3189 hnd1,
3192 &info1);
3193 if ( !W_ERROR_IS_OK(werror) ) {
3194 printf("failed (%s)\n", win_errstr(werror));
3195 talloc_destroy(mem_ctx);
3196 return false;
3198 printf("ok\n");
3200 printf("Retrieving printer properties for %s...", cli2->desthost);
3201 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3202 hnd2,
3205 &info2);
3206 if ( !W_ERROR_IS_OK(werror) ) {
3207 printf("failed (%s)\n", win_errstr(werror));
3208 talloc_destroy(mem_ctx);
3209 return false;
3211 printf("ok\n");
3213 talloc_destroy(mem_ctx);
3215 return true;
3218 /****************************************************************************
3219 ****************************************************************************/
3221 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3222 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3224 union spoolss_PrinterInfo info1, info2;
3225 WERROR werror;
3226 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3227 struct security_descriptor *sd1, *sd2;
3228 bool result = true;
3231 printf("Retrieving printer security for %s...", cli1->desthost);
3232 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3233 hnd1,
3236 &info1);
3237 if ( !W_ERROR_IS_OK(werror) ) {
3238 printf("failed (%s)\n", win_errstr(werror));
3239 result = false;
3240 goto done;
3242 printf("ok\n");
3244 printf("Retrieving printer security for %s...", cli2->desthost);
3245 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3246 hnd2,
3249 &info2);
3250 if ( !W_ERROR_IS_OK(werror) ) {
3251 printf("failed (%s)\n", win_errstr(werror));
3252 result = false;
3253 goto done;
3255 printf("ok\n");
3258 printf("++ ");
3260 sd1 = info1.info3.secdesc;
3261 sd2 = info2.info3.secdesc;
3263 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3264 printf("NULL secdesc!\n");
3265 result = false;
3266 goto done;
3269 if (!security_descriptor_equal( sd1, sd2 ) ) {
3270 printf("Security Descriptors *not* equal!\n");
3271 result = false;
3272 goto done;
3275 printf("Security descriptors match\n");
3277 done:
3278 talloc_destroy(mem_ctx);
3279 return result;
3283 /****************************************************************************
3284 ****************************************************************************/
3286 extern struct user_auth_info *rpcclient_auth_info;
3288 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3289 TALLOC_CTX *mem_ctx, int argc,
3290 const char **argv)
3292 const char *printername;
3293 char *printername_path = NULL;
3294 struct cli_state *cli_server2 = NULL;
3295 struct rpc_pipe_client *cli2 = NULL;
3296 struct policy_handle hPrinter1, hPrinter2;
3297 NTSTATUS nt_status;
3298 WERROR werror;
3300 if ( argc != 3 ) {
3301 printf("Usage: %s <printer> <server>\n", argv[0]);
3302 return WERR_OK;
3305 printername = argv[1];
3307 /* first get the connection to the remote server */
3309 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3310 NULL, 0,
3311 "IPC$", "IPC",
3312 get_cmdline_auth_info_username(rpcclient_auth_info),
3313 lp_workgroup(),
3314 get_cmdline_auth_info_password(rpcclient_auth_info),
3315 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3316 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3318 if ( !NT_STATUS_IS_OK(nt_status) )
3319 return WERR_GENERAL_FAILURE;
3321 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3322 &cli2);
3323 if (!NT_STATUS_IS_OK(nt_status)) {
3324 printf("failed to open spoolss pipe on server %s (%s)\n",
3325 argv[2], nt_errstr(nt_status));
3326 return WERR_GENERAL_FAILURE;
3329 /* now open up both printers */
3331 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3333 printf("Opening %s...", printername_path);
3335 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3336 printername_path,
3337 PRINTER_ALL_ACCESS,
3338 &hPrinter1);
3339 if ( !W_ERROR_IS_OK(werror) ) {
3340 printf("failed (%s)\n", win_errstr(werror));
3341 goto done;
3343 printf("ok\n");
3345 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3347 printf("Opening %s...", printername_path);
3348 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3349 printername_path,
3350 PRINTER_ALL_ACCESS,
3351 &hPrinter2);
3352 if ( !W_ERROR_IS_OK(werror) ) {
3353 printf("failed (%s)\n", win_errstr(werror));
3354 goto done;
3356 printf("ok\n");
3358 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3359 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3360 #if 0
3361 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3362 #endif
3365 done:
3366 /* cleanup */
3368 printf("Closing printers...");
3369 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3370 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3371 printf("ok\n");
3373 /* close the second remote connection */
3375 cli_shutdown( cli_server2 );
3376 return WERR_OK;
3379 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3381 printf("print_processor_name: %s\n", r->print_processor_name);
3384 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3385 TALLOC_CTX *mem_ctx, int argc,
3386 const char **argv)
3388 WERROR werror;
3389 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3390 uint32_t num_procs, level = 1, i;
3391 union spoolss_PrintProcessorInfo *procs;
3393 /* Parse the command arguments */
3395 if (argc < 1 || argc > 4) {
3396 printf ("Usage: %s [environment] [level]\n", argv[0]);
3397 return WERR_OK;
3400 if (argc >= 2) {
3401 environment = argv[1];
3404 if (argc == 3) {
3405 level = atoi(argv[2]);
3408 /* Enumerate Print Processors */
3410 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3411 cli->srv_name_slash,
3412 environment,
3413 level,
3415 &num_procs,
3416 &procs);
3417 if (!W_ERROR_IS_OK(werror))
3418 goto done;
3420 /* Display output */
3422 for (i = 0; i < num_procs; i++) {
3423 switch (level) {
3424 case 1:
3425 display_proc_info1(&procs[i].info1);
3426 break;
3430 done:
3431 return werror;
3434 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3436 printf("name_array: %s\n", r->name_array);
3439 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3440 TALLOC_CTX *mem_ctx, int argc,
3441 const char **argv)
3443 WERROR werror;
3444 const char *print_processor_name = "winprint";
3445 uint32_t num_procs, level = 1, i;
3446 union spoolss_PrintProcDataTypesInfo *procs;
3448 /* Parse the command arguments */
3450 if (argc < 1 || argc > 4) {
3451 printf ("Usage: %s [environment] [level]\n", argv[0]);
3452 return WERR_OK;
3455 if (argc >= 2) {
3456 print_processor_name = argv[1];
3459 if (argc == 3) {
3460 level = atoi(argv[2]);
3463 /* Enumerate Print Processor Data Types */
3465 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3466 cli->srv_name_slash,
3467 print_processor_name,
3468 level,
3470 &num_procs,
3471 &procs);
3472 if (!W_ERROR_IS_OK(werror))
3473 goto done;
3475 /* Display output */
3477 for (i = 0; i < num_procs; i++) {
3478 switch (level) {
3479 case 1:
3480 display_proc_data_types_info1(&procs[i].info1);
3481 break;
3485 done:
3486 return werror;
3489 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3491 printf("monitor_name: %s\n", r->monitor_name);
3494 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3496 printf("monitor_name: %s\n", r->monitor_name);
3497 printf("environment: %s\n", r->environment);
3498 printf("dll_name: %s\n", r->dll_name);
3501 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3502 TALLOC_CTX *mem_ctx, int argc,
3503 const char **argv)
3505 WERROR werror;
3506 uint32_t count, level = 1, i;
3507 union spoolss_MonitorInfo *info;
3509 /* Parse the command arguments */
3511 if (argc > 2) {
3512 printf("Usage: %s [level]\n", argv[0]);
3513 return WERR_OK;
3516 if (argc == 2) {
3517 level = atoi(argv[1]);
3520 /* Enumerate Print Monitors */
3522 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3523 cli->srv_name_slash,
3524 level,
3526 &count,
3527 &info);
3528 if (!W_ERROR_IS_OK(werror)) {
3529 goto done;
3532 /* Display output */
3534 for (i = 0; i < count; i++) {
3535 switch (level) {
3536 case 1:
3537 display_monitor1(&info[i].info1);
3538 break;
3539 case 2:
3540 display_monitor2(&info[i].info2);
3541 break;
3545 done:
3546 return werror;
3549 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3550 TALLOC_CTX *mem_ctx, int argc,
3551 const char **argv)
3553 WERROR result;
3554 NTSTATUS status;
3555 struct policy_handle handle, gdi_handle;
3556 const char *printername;
3557 struct spoolss_DevmodeContainer devmode_ctr;
3559 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3561 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3562 printername,
3563 SEC_FLAG_MAXIMUM_ALLOWED,
3564 &handle);
3565 if (!W_ERROR_IS_OK(result)) {
3566 return result;
3569 ZERO_STRUCT(devmode_ctr);
3571 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3572 &handle,
3573 &gdi_handle,
3574 &devmode_ctr,
3575 &result);
3576 if (!W_ERROR_IS_OK(result)) {
3577 goto done;
3580 done:
3581 if (is_valid_policy_hnd(&gdi_handle)) {
3582 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3584 if (is_valid_policy_hnd(&handle)) {
3585 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3588 return result;
3591 /* List of commands exported by this module */
3592 struct cmd_set spoolss_commands[] = {
3594 { "SPOOLSS" },
3596 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3597 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3598 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3599 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3600 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3601 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3602 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3603 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3604 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3605 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3606 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3607 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3608 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3609 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3610 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3611 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3612 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3613 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3614 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3615 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3616 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3617 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3618 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3619 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3620 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3621 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3622 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3623 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3624 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3625 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3626 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3627 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3628 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3629 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3630 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3631 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3633 { NULL }