Introduce system MIT krb5 build with --with-system-mitkrb5 option.
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blobb189fd7379ec6ac12c4af27e8ac0fba6d0638c16
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/ndr_spoolss_c.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
30 #include "nt_printing.h"
31 #include "../libcli/security/display_sec.h"
32 #include "../libcli/security/security_descriptor.h"
33 #include "../libcli/registry/util_reg.h"
34 #include "libsmb/libsmb.h"
36 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
37 { \
38 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
39 _cli->srv_name_slash, _arg); \
40 W_ERROR_HAVE_NO_MEMORY(_printername); \
43 /* The version int is used by getdrivers. Note that
44 all architecture strings that support mutliple
45 versions must be grouped together since enumdrivers
46 uses this property to prevent issuing multiple
47 enumdriver calls for the same arch */
50 static const struct print_architecture_table_node archi_table[]= {
52 {"Windows 4.0", "WIN40", 0 },
53 {"Windows NT x86", "W32X86", 2 },
54 {"Windows NT x86", "W32X86", 3 },
55 {"Windows NT R4000", "W32MIPS", 2 },
56 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
57 {"Windows NT PowerPC", "W32PPC", 2 },
58 {"Windows IA64", "IA64", 3 },
59 {"Windows x64", "x64", 3 },
60 {NULL, "", -1 }
63 /**
64 * @file
66 * rpcclient module for SPOOLSS rpc pipe.
68 * This generally just parses and checks command lines, and then calls
69 * a cli_spoolss function.
70 **/
72 /****************************************************************************
73 function to do the mapping between the long architecture name and
74 the short one.
75 ****************************************************************************/
77 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
79 int i=-1;
81 DEBUG(107,("Getting architecture dependent directory\n"));
82 do {
83 i++;
84 } while ( (archi_table[i].long_archi!=NULL ) &&
85 strcasecmp_m(long_archi, archi_table[i].long_archi) );
87 if (archi_table[i].long_archi==NULL) {
88 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
89 return NULL;
92 /* this might be client code - but shouldn't this be an fstrcpy etc? */
95 DEBUGADD(108,("index: [%d]\n", i));
96 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
97 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
99 return archi_table[i].short_archi;
102 /****************************************************************************
103 ****************************************************************************/
105 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
106 TALLOC_CTX *mem_ctx,
107 int argc, const char **argv)
109 WERROR werror;
110 struct policy_handle hnd;
111 uint32_t access_mask = PRINTER_ALL_ACCESS;
112 struct dcerpc_binding_handle *b = cli->binding_handle;
114 if (argc < 2) {
115 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
116 return WERR_OK;
119 if (argc >= 3) {
120 sscanf(argv[2], "%x", &access_mask);
123 /* Open the printer handle */
125 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
126 argv[1],
127 access_mask,
128 &hnd);
129 if (W_ERROR_IS_OK(werror)) {
130 printf("Printer %s opened successfully\n", argv[1]);
131 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
133 if (!W_ERROR_IS_OK(werror)) {
134 printf("Error closing printer handle! (%s)\n",
135 get_dos_error_msg(werror));
139 return werror;
142 /****************************************************************************
143 ****************************************************************************/
145 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
146 TALLOC_CTX *mem_ctx,
147 int argc, const char **argv)
149 WERROR werror;
150 struct policy_handle hnd;
151 uint32_t access_mask = PRINTER_ALL_ACCESS;
152 NTSTATUS status;
153 struct spoolss_DevmodeContainer devmode_ctr;
154 struct dcerpc_binding_handle *b = cli->binding_handle;
156 ZERO_STRUCT(devmode_ctr);
158 if (argc < 2) {
159 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
160 return WERR_OK;
163 if (argc >= 3) {
164 sscanf(argv[2], "%x", &access_mask);
167 /* Open the printer handle */
169 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
170 argv[1],
171 NULL,
172 devmode_ctr,
173 access_mask,
174 &hnd,
175 &werror);
176 if (!NT_STATUS_IS_OK(status)) {
177 return ntstatus_to_werror(status);
179 if (W_ERROR_IS_OK(werror)) {
180 printf("Printer %s opened successfully\n", argv[1]);
181 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
183 if (!W_ERROR_IS_OK(werror)) {
184 printf("Error closing printer handle! (%s)\n",
185 get_dos_error_msg(werror));
189 return werror;
192 /****************************************************************************
193 ****************************************************************************/
195 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
197 if (!r)
198 return;
200 printf("\tprintername:[%s]\n", r->printername);
201 printf("\tservername:[%s]\n", r->servername);
202 printf("\tcjobs:[0x%x]\n", r->cjobs);
203 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
204 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
205 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
206 r->time.day, r->time.day_of_week);
207 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
208 r->time.second, r->time.millisecond);
210 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
211 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
213 printf("\tversion:[0x%x]\n", r->version);
214 printf("\tfree_build:[0x%x]\n", r->free_build);
215 printf("\tspooling:[0x%x]\n", r->spooling);
216 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
217 printf("\tsession_counter:[0x%x]\n", r->session_counter);
218 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
219 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
220 printf("\tjob_error:[0x%x]\n", r->job_error);
221 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
222 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
223 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
224 printf("\tchange_id:[0x%x]\n", r->change_id);
225 printf("\tlast_error: %s\n", win_errstr(r->last_error));
226 printf("\tstatus:[0x%x]\n", r->status);
227 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
228 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
229 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
230 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
231 printf("\tref_ic:[0x%x]\n", r->ref_ic);
232 printf("\treserved2:[0x%x]\n", r->reserved2);
233 printf("\treserved3:[0x%x]\n", r->reserved3);
235 printf("\n");
238 /****************************************************************************
239 ****************************************************************************/
241 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
243 printf("\tflags:[0x%x]\n", r->flags);
244 printf("\tname:[%s]\n", r->name);
245 printf("\tdescription:[%s]\n", r->description);
246 printf("\tcomment:[%s]\n", r->comment);
248 printf("\n");
251 /****************************************************************************
252 ****************************************************************************/
254 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
256 printf("\tservername:[%s]\n", r->servername);
257 printf("\tprintername:[%s]\n", r->printername);
258 printf("\tsharename:[%s]\n", r->sharename);
259 printf("\tportname:[%s]\n", r->portname);
260 printf("\tdrivername:[%s]\n", r->drivername);
261 printf("\tcomment:[%s]\n", r->comment);
262 printf("\tlocation:[%s]\n", r->location);
263 printf("\tsepfile:[%s]\n", r->sepfile);
264 printf("\tprintprocessor:[%s]\n", r->printprocessor);
265 printf("\tdatatype:[%s]\n", r->datatype);
266 printf("\tparameters:[%s]\n", r->parameters);
267 printf("\tattributes:[0x%x]\n", r->attributes);
268 printf("\tpriority:[0x%x]\n", r->priority);
269 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
270 printf("\tstarttime:[0x%x]\n", r->starttime);
271 printf("\tuntiltime:[0x%x]\n", r->untiltime);
272 printf("\tstatus:[0x%x]\n", r->status);
273 printf("\tcjobs:[0x%x]\n", r->cjobs);
274 printf("\taverageppm:[0x%x]\n", r->averageppm);
276 if (r->secdesc)
277 display_sec_desc(r->secdesc);
279 printf("\n");
282 /****************************************************************************
283 ****************************************************************************/
285 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
287 display_sec_desc(r->secdesc);
289 printf("\n");
292 /****************************************************************************
293 ****************************************************************************/
295 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
297 printf("\tservername:[%s]\n", r->servername);
298 printf("\tprintername:[%s]\n", r->printername);
299 printf("\tattributes:[0x%x]\n", r->attributes);
300 printf("\n");
303 /****************************************************************************
304 ****************************************************************************/
306 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
308 printf("\tprintername:[%s]\n", r->printername);
309 printf("\tportname:[%s]\n", r->portname);
310 printf("\tattributes:[0x%x]\n", r->attributes);
311 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
312 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
313 printf("\n");
316 /****************************************************************************
317 ****************************************************************************/
319 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
321 printf("\tstatus:[0x%x]\n", r->status);
322 printf("\n");
325 /****************************************************************************
326 ****************************************************************************/
328 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
330 printf("\tguid:[%s]\n", r->guid);
331 printf("\taction:[0x%x]\n", r->action);
332 printf("\n");
335 /****************************************************************************
336 ****************************************************************************/
338 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
339 TALLOC_CTX *mem_ctx,
340 int argc, const char **argv)
342 WERROR result;
343 uint32_t level = 1;
344 union spoolss_PrinterInfo *info;
345 uint32_t i, count;
346 const char *name;
347 uint32_t flags = PRINTER_ENUM_LOCAL;
349 if (argc > 4) {
350 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
351 return WERR_OK;
354 if (argc >= 2) {
355 level = atoi(argv[1]);
358 if (argc >= 3) {
359 name = argv[2];
360 } else {
361 name = cli->srv_name_slash;
364 if (argc == 4) {
365 flags = atoi(argv[3]);
368 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
369 flags,
370 name,
371 level,
373 &count,
374 &info);
375 if (W_ERROR_IS_OK(result)) {
377 if (!count) {
378 printf ("No printers returned.\n");
379 goto done;
382 for (i = 0; i < count; i++) {
383 switch (level) {
384 case 0:
385 display_print_info0(&info[i].info0);
386 break;
387 case 1:
388 display_print_info1(&info[i].info1);
389 break;
390 case 2:
391 display_print_info2(&info[i].info2);
392 break;
393 case 3:
394 display_print_info3(&info[i].info3);
395 break;
396 case 4:
397 display_print_info4(&info[i].info4);
398 break;
399 case 5:
400 display_print_info5(&info[i].info5);
401 break;
402 case 6:
403 display_print_info6(&info[i].info6);
404 break;
405 default:
406 printf("unknown info level %d\n", level);
407 goto done;
411 done:
413 return result;
416 /****************************************************************************
417 ****************************************************************************/
419 static void display_port_info_1(struct spoolss_PortInfo1 *r)
421 printf("\tPort Name:\t[%s]\n", r->port_name);
424 /****************************************************************************
425 ****************************************************************************/
427 static void display_port_info_2(struct spoolss_PortInfo2 *r)
429 printf("\tPort Name:\t[%s]\n", r->port_name);
430 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
431 printf("\tDescription:\t[%s]\n", r->description);
432 printf("\tPort Type:\t" );
433 if (r->port_type) {
434 int comma = 0; /* hack */
435 printf( "[" );
436 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
437 printf( "Read" );
438 comma = 1;
440 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
441 printf( "%sWrite", comma ? ", " : "" );
442 comma = 1;
444 /* These two have slightly different interpretations
445 on 95/98/ME but I'm disregarding that for now */
446 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
447 printf( "%sRedirected", comma ? ", " : "" );
448 comma = 1;
450 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
451 printf( "%sNet-Attached", comma ? ", " : "" );
453 printf( "]\n" );
454 } else {
455 printf( "[Unset]\n" );
457 printf("\tReserved:\t[%d]\n", r->reserved);
458 printf("\n");
461 /****************************************************************************
462 ****************************************************************************/
464 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
465 TALLOC_CTX *mem_ctx, int argc,
466 const char **argv)
468 WERROR result;
469 uint32_t level = 1;
470 uint32_t count;
471 union spoolss_PortInfo *info;
473 if (argc > 2) {
474 printf("Usage: %s [level]\n", argv[0]);
475 return WERR_OK;
478 if (argc == 2) {
479 level = atoi(argv[1]);
482 /* Enumerate ports */
484 result = rpccli_spoolss_enumports(cli, mem_ctx,
485 cli->srv_name_slash,
486 level,
488 &count,
489 &info);
490 if (W_ERROR_IS_OK(result)) {
491 int i;
493 for (i = 0; i < count; i++) {
494 switch (level) {
495 case 1:
496 display_port_info_1(&info[i].info1);
497 break;
498 case 2:
499 display_port_info_2(&info[i].info2);
500 break;
501 default:
502 printf("unknown info level %d\n", level);
503 break;
508 return result;
511 /****************************************************************************
512 ****************************************************************************/
514 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
515 TALLOC_CTX *mem_ctx,
516 int argc, const char **argv)
518 struct policy_handle pol;
519 WERROR result;
520 NTSTATUS status;
521 uint32_t info_level = 2;
522 union spoolss_PrinterInfo info;
523 struct spoolss_SetPrinterInfoCtr info_ctr;
524 struct spoolss_SetPrinterInfo2 info2;
525 const char *printername, *comment = NULL;
526 struct spoolss_DevmodeContainer devmode_ctr;
527 struct sec_desc_buf secdesc_ctr;
528 struct dcerpc_binding_handle *b = cli->binding_handle;
530 if (argc == 1 || argc > 3) {
531 printf("Usage: %s printername comment\n", argv[0]);
533 return WERR_OK;
536 /* Open a printer handle */
537 if (argc == 3) {
538 comment = argv[2];
541 ZERO_STRUCT(devmode_ctr);
542 ZERO_STRUCT(secdesc_ctr);
544 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
546 /* get a printer handle */
547 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
548 printername,
549 PRINTER_ALL_ACCESS,
550 &pol);
551 if (!W_ERROR_IS_OK(result))
552 goto done;
554 /* Get printer info */
555 result = rpccli_spoolss_getprinter(cli, mem_ctx,
556 &pol,
557 info_level,
559 &info);
560 if (!W_ERROR_IS_OK(result))
561 goto done;
564 /* Modify the comment. */
565 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
566 info2.comment = comment;
568 info_ctr.level = 2;
569 info_ctr.info.info2 = &info2;
571 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
572 &pol,
573 &info_ctr,
574 &devmode_ctr,
575 &secdesc_ctr,
576 0, /* command */
577 &result);
578 if (!NT_STATUS_IS_OK(status)) {
579 result = ntstatus_to_werror(status);
580 goto done;
582 if (W_ERROR_IS_OK(result))
583 printf("Success in setting comment.\n");
585 done:
586 if (is_valid_policy_hnd(&pol)) {
587 WERROR _result;
588 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
591 return result;
594 /****************************************************************************
595 ****************************************************************************/
597 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
598 TALLOC_CTX *mem_ctx,
599 int argc, const char **argv)
601 struct policy_handle pol;
602 WERROR result;
603 NTSTATUS status;
604 uint32_t info_level = 2;
605 union spoolss_PrinterInfo info;
606 const char *printername,
607 *new_printername = NULL;
608 struct spoolss_SetPrinterInfoCtr info_ctr;
609 struct spoolss_SetPrinterInfo2 info2;
610 struct spoolss_DevmodeContainer devmode_ctr;
611 struct sec_desc_buf secdesc_ctr;
612 struct dcerpc_binding_handle *b = cli->binding_handle;
614 ZERO_STRUCT(devmode_ctr);
615 ZERO_STRUCT(secdesc_ctr);
617 if (argc == 1 || argc > 3) {
618 printf("Usage: %s printername new_printername\n", argv[0]);
620 return WERR_OK;
623 /* Open a printer handle */
624 if (argc == 3) {
625 new_printername = argv[2];
628 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
630 /* get a printer handle */
631 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
632 printername,
633 PRINTER_ALL_ACCESS,
634 &pol);
635 if (!W_ERROR_IS_OK(result))
636 goto done;
638 /* Get printer info */
639 result = rpccli_spoolss_getprinter(cli, mem_ctx,
640 &pol,
641 info_level,
643 &info);
644 if (!W_ERROR_IS_OK(result))
645 goto done;
647 /* Modify the printername. */
648 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
649 info2.printername = new_printername;
651 info_ctr.level = 2;
652 info_ctr.info.info2 = &info2;
654 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
655 &pol,
656 &info_ctr,
657 &devmode_ctr,
658 &secdesc_ctr,
659 0, /* command */
660 &result);
661 if (!NT_STATUS_IS_OK(status)) {
662 result = ntstatus_to_werror(status);
663 goto done;
665 if (W_ERROR_IS_OK(result))
666 printf("Success in setting printername.\n");
668 done:
669 if (is_valid_policy_hnd(&pol)) {
670 WERROR _result;
671 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
674 return result;
677 /****************************************************************************
678 ****************************************************************************/
680 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
681 TALLOC_CTX *mem_ctx,
682 int argc, const char **argv)
684 struct policy_handle pol;
685 WERROR result;
686 uint32_t level = 1;
687 const char *printername;
688 union spoolss_PrinterInfo info;
689 struct dcerpc_binding_handle *b = cli->binding_handle;
691 if (argc == 1 || argc > 3) {
692 printf("Usage: %s <printername> [level]\n", argv[0]);
693 return WERR_OK;
696 /* Open a printer handle */
697 if (argc == 3) {
698 level = atoi(argv[2]);
701 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
703 /* get a printer handle */
705 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
706 printername,
707 SEC_FLAG_MAXIMUM_ALLOWED,
708 &pol);
709 if (!W_ERROR_IS_OK(result)) {
710 goto done;
713 /* Get printer info */
715 result = rpccli_spoolss_getprinter(cli, mem_ctx,
716 &pol,
717 level,
719 &info);
720 if (!W_ERROR_IS_OK(result)) {
721 goto done;
724 /* Display printer info */
725 switch (level) {
726 case 0:
727 display_print_info0(&info.info0);
728 break;
729 case 1:
730 display_print_info1(&info.info1);
731 break;
732 case 2:
733 display_print_info2(&info.info2);
734 break;
735 case 3:
736 display_print_info3(&info.info3);
737 break;
738 case 4:
739 display_print_info4(&info.info4);
740 break;
741 case 5:
742 display_print_info5(&info.info5);
743 break;
744 case 6:
745 display_print_info6(&info.info6);
746 break;
747 case 7:
748 display_print_info7(&info.info7);
749 break;
750 default:
751 printf("unknown info level %d\n", level);
752 break;
754 done:
755 if (is_valid_policy_hnd(&pol)) {
756 WERROR _result;
757 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
760 return result;
763 /****************************************************************************
764 ****************************************************************************/
766 static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
768 const char *text = NULL;
770 switch(type) {
771 case REG_DWORD:
772 if (blob.length == sizeof(uint32)) {
773 printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
774 } else {
775 printf("%s: REG_DWORD: <invalid>\n", name);
777 break;
778 case REG_SZ:
779 pull_reg_sz(talloc_tos(), &blob, &text);
780 printf("%s: REG_SZ: %s\n", name, text ? text : "");
781 break;
782 case REG_BINARY: {
783 char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
784 size_t i, len;
785 printf("%s: REG_BINARY:", name);
786 len = strlen(hex);
787 for (i=0; i<len; i++) {
788 if (hex[i] == '\0') {
789 break;
791 if (i%40 == 0) {
792 putchar('\n');
794 putchar(hex[i]);
796 TALLOC_FREE(hex);
797 putchar('\n');
798 break;
800 case REG_MULTI_SZ: {
801 uint32_t i;
802 const char **values;
804 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
805 d_printf("pull_reg_multi_sz failed\n");
806 break;
809 printf("%s: REG_MULTI_SZ: \n", name);
810 for (i=0; values[i] != NULL; i++) {
811 d_printf("%s\n", values[i]);
813 TALLOC_FREE(values);
814 break;
816 default:
817 printf("%s: unknown type %d\n", name, type);
822 /****************************************************************************
823 ****************************************************************************/
825 static void display_printer_data(const char *v,
826 enum winreg_Type type,
827 uint8_t *data,
828 uint32_t length)
830 int i;
831 union spoolss_PrinterData r;
832 DATA_BLOB blob = data_blob_const(data, length);
833 WERROR result;
835 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
836 if (!W_ERROR_IS_OK(result)) {
837 return;
840 switch (type) {
841 case REG_DWORD:
842 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
843 break;
844 case REG_SZ:
845 printf("%s: REG_SZ: %s\n", v, r.string);
846 break;
847 case REG_BINARY: {
848 char *hex = hex_encode_talloc(NULL,
849 r.binary.data, r.binary.length);
850 size_t len;
851 printf("%s: REG_BINARY:", v);
852 len = strlen(hex);
853 for (i=0; i<len; i++) {
854 if (hex[i] == '\0') {
855 break;
857 if (i%40 == 0) {
858 putchar('\n');
860 putchar(hex[i]);
862 TALLOC_FREE(hex);
863 putchar('\n');
864 break;
866 case REG_MULTI_SZ:
867 printf("%s: REG_MULTI_SZ: ", v);
868 for (i=0; r.string_array[i] != NULL; i++) {
869 printf("%s ", r.string_array[i]);
871 printf("\n");
872 break;
873 default:
874 printf("%s: unknown type 0x%02x:\n", v, type);
875 break;
879 /****************************************************************************
880 ****************************************************************************/
882 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
883 TALLOC_CTX *mem_ctx,
884 int argc, const char **argv)
886 struct policy_handle pol;
887 WERROR result;
888 fstring printername;
889 const char *valuename;
890 enum winreg_Type type;
891 uint8_t *data;
892 uint32_t needed;
893 struct dcerpc_binding_handle *b = cli->binding_handle;
895 if (argc != 3) {
896 printf("Usage: %s <printername> <valuename>\n", argv[0]);
897 printf("<printername> of . queries print server\n");
898 return WERR_OK;
900 valuename = argv[2];
902 /* Open a printer handle */
904 if (strncmp(argv[1], ".", sizeof(".")) == 0)
905 fstrcpy(printername, cli->srv_name_slash);
906 else
907 slprintf(printername, sizeof(printername)-1, "%s\\%s",
908 cli->srv_name_slash, argv[1]);
910 /* get a printer handle */
912 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
913 printername,
914 SEC_FLAG_MAXIMUM_ALLOWED,
915 &pol);
916 if (!W_ERROR_IS_OK(result))
917 goto done;
919 /* Get printer info */
921 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
922 &pol,
923 valuename,
925 &type,
926 &needed,
927 &data);
928 if (!W_ERROR_IS_OK(result))
929 goto done;
931 /* Display printer data */
933 display_printer_data(valuename, type, data, needed);
935 done:
936 if (is_valid_policy_hnd(&pol)) {
937 WERROR _result;
938 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
941 return result;
944 /****************************************************************************
945 ****************************************************************************/
947 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
948 TALLOC_CTX *mem_ctx,
949 int argc, const char **argv)
951 struct policy_handle pol;
952 WERROR result;
953 NTSTATUS status;
954 fstring printername;
955 const char *valuename, *keyname;
957 enum winreg_Type type;
958 uint8_t *data = NULL;
959 uint32_t offered = 0;
960 uint32_t needed;
961 struct dcerpc_binding_handle *b = cli->binding_handle;
963 if (argc != 4) {
964 printf("Usage: %s <printername> <keyname> <valuename>\n",
965 argv[0]);
966 printf("<printername> of . queries print server\n");
967 return WERR_OK;
969 valuename = argv[3];
970 keyname = argv[2];
972 /* Open a printer handle */
974 if (strncmp(argv[1], ".", sizeof(".")) == 0)
975 fstrcpy(printername, cli->srv_name_slash);
976 else
977 slprintf(printername, sizeof(printername)-1, "%s\\%s",
978 cli->srv_name_slash, argv[1]);
980 /* get a printer handle */
982 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
983 printername,
984 SEC_FLAG_MAXIMUM_ALLOWED,
985 &pol);
986 if (!W_ERROR_IS_OK(result))
987 goto done;
989 /* Get printer info */
991 data = talloc_zero_array(mem_ctx, uint8_t, offered);
992 if (!data) {
993 goto done;
996 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
997 &pol,
998 keyname,
999 valuename,
1000 &type,
1001 data,
1002 offered,
1003 &needed,
1004 &result);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 result = ntstatus_to_werror(status);
1007 goto done;
1009 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1010 offered = needed;
1011 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1012 if (!data) {
1013 goto done;
1015 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1016 &pol,
1017 keyname,
1018 valuename,
1019 &type,
1020 data,
1021 offered,
1022 &needed,
1023 &result);
1026 if (!NT_STATUS_IS_OK(status)) {
1027 result = ntstatus_to_werror(status);
1028 goto done;
1031 if (!W_ERROR_IS_OK(result))
1032 goto done;
1034 /* Display printer data */
1036 display_printer_data(valuename, type, data, needed);
1039 done:
1040 if (is_valid_policy_hnd(&pol)) {
1041 WERROR _result;
1042 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1045 return result;
1048 /****************************************************************************
1049 ****************************************************************************/
1051 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1053 if (!r) {
1054 return;
1057 printf("Printer Driver Info 1:\n");
1058 printf("\tDriver Name: [%s]\n", r->driver_name);
1059 printf("\n");
1062 /****************************************************************************
1063 ****************************************************************************/
1065 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1067 if (!r) {
1068 return;
1071 printf("Printer Driver Info 2:\n");
1072 printf("\tVersion: [%x]\n", r->version);
1073 printf("\tDriver Name: [%s]\n", r->driver_name);
1074 printf("\tArchitecture: [%s]\n", r->architecture);
1075 printf("\tDriver Path: [%s]\n", r->driver_path);
1076 printf("\tDatafile: [%s]\n", r->data_file);
1077 printf("\tConfigfile: [%s]\n", r->config_file);
1078 printf("\n");
1081 /****************************************************************************
1082 ****************************************************************************/
1084 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1086 int i;
1088 if (!r) {
1089 return;
1092 printf("Printer Driver Info 3:\n");
1093 printf("\tVersion: [%x]\n", r->version);
1094 printf("\tDriver Name: [%s]\n", r->driver_name);
1095 printf("\tArchitecture: [%s]\n", r->architecture);
1096 printf("\tDriver Path: [%s]\n", r->driver_path);
1097 printf("\tDatafile: [%s]\n", r->data_file);
1098 printf("\tConfigfile: [%s]\n", r->config_file);
1099 printf("\tHelpfile: [%s]\n", r->help_file);
1101 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1102 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1105 printf("\tMonitorname: [%s]\n", r->monitor_name);
1106 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1107 printf("\n");
1110 /****************************************************************************
1111 ****************************************************************************/
1113 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1115 int i;
1117 if (!r) {
1118 return;
1121 printf("Printer Driver Info 4:\n");
1122 printf("\tVersion: [%x]\n", r->version);
1123 printf("\tDriver Name: [%s]\n", r->driver_name);
1124 printf("\tArchitecture: [%s]\n", r->architecture);
1125 printf("\tDriver Path: [%s]\n", r->driver_path);
1126 printf("\tDatafile: [%s]\n", r->data_file);
1127 printf("\tConfigfile: [%s]\n", r->config_file);
1128 printf("\tHelpfile: [%s]\n", r->help_file);
1130 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1131 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1134 printf("\tMonitorname: [%s]\n", r->monitor_name);
1135 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1137 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1138 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1140 printf("\n");
1143 /****************************************************************************
1144 ****************************************************************************/
1146 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1148 if (!r) {
1149 return;
1152 printf("Printer Driver Info 5:\n");
1153 printf("\tVersion: [%x]\n", r->version);
1154 printf("\tDriver Name: [%s]\n", r->driver_name);
1155 printf("\tArchitecture: [%s]\n", r->architecture);
1156 printf("\tDriver Path: [%s]\n", r->driver_path);
1157 printf("\tDatafile: [%s]\n", r->data_file);
1158 printf("\tConfigfile: [%s]\n", r->config_file);
1159 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1160 printf("\tConfig Version: [0x%x]\n", r->config_version);
1161 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1162 printf("\n");
1165 /****************************************************************************
1166 ****************************************************************************/
1168 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1170 int i;
1172 if (!r) {
1173 return;
1176 printf("Printer Driver Info 6:\n");
1177 printf("\tVersion: [%x]\n", r->version);
1178 printf("\tDriver Name: [%s]\n", r->driver_name);
1179 printf("\tArchitecture: [%s]\n", r->architecture);
1180 printf("\tDriver Path: [%s]\n", r->driver_path);
1181 printf("\tDatafile: [%s]\n", r->data_file);
1182 printf("\tConfigfile: [%s]\n", r->config_file);
1183 printf("\tHelpfile: [%s]\n", r->help_file);
1185 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1186 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1189 printf("\tMonitorname: [%s]\n", r->monitor_name);
1190 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1192 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1193 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1196 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1197 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1198 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1199 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1200 printf("\tHardware ID: [%s]\n", r->hardware_id);
1201 printf("\tProvider: [%s]\n", r->provider);
1203 printf("\n");
1206 /****************************************************************************
1207 ****************************************************************************/
1209 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1211 int i;
1213 if (!r) {
1214 return;
1217 printf("Printer Driver Info 8:\n");
1218 printf("\tVersion: [%x]\n", r->version);
1219 printf("\tDriver Name: [%s]\n", r->driver_name);
1220 printf("\tArchitecture: [%s]\n", r->architecture);
1221 printf("\tDriver Path: [%s]\n", r->driver_path);
1222 printf("\tDatafile: [%s]\n", r->data_file);
1223 printf("\tConfigfile: [%s]\n", r->config_file);
1224 printf("\tHelpfile: [%s]\n", r->help_file);
1225 printf("\tMonitorname: [%s]\n", r->monitor_name);
1226 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1228 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1229 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1232 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1233 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1236 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1237 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1238 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1239 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1240 printf("\tHardware ID: [%s]\n", r->hardware_id);
1241 printf("\tProvider: [%s]\n", r->provider);
1242 printf("\tPrint Processor: [%s]\n", r->print_processor);
1243 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1244 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1245 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1247 printf("\tInf Path: [%s]\n", r->inf_path);
1248 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1249 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1250 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1252 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1253 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1254 (long long unsigned int)r->min_inbox_driver_ver_version);
1256 printf("\n");
1259 /****************************************************************************
1260 ****************************************************************************/
1262 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1263 TALLOC_CTX *mem_ctx,
1264 int argc, const char **argv)
1266 struct policy_handle pol;
1267 WERROR werror;
1268 uint32_t level = 3;
1269 const char *printername;
1270 uint32_t i;
1271 bool success = false;
1272 union spoolss_DriverInfo info;
1273 uint32_t server_major_version;
1274 uint32_t server_minor_version;
1275 struct dcerpc_binding_handle *b = cli->binding_handle;
1277 if ((argc == 1) || (argc > 3)) {
1278 printf("Usage: %s <printername> [level]\n", argv[0]);
1279 return WERR_OK;
1282 /* get the arguments need to open the printer handle */
1284 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1286 if (argc == 3) {
1287 level = atoi(argv[2]);
1290 /* Open a printer handle */
1292 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1293 printername,
1294 PRINTER_ACCESS_USE,
1295 &pol);
1296 if (!W_ERROR_IS_OK(werror)) {
1297 printf("Error opening printer handle for %s!\n", printername);
1298 return werror;
1301 /* loop through and print driver info level for each architecture */
1303 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1305 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1306 &pol,
1307 archi_table[i].long_archi,
1308 level,
1309 0, /* offered */
1310 archi_table[i].version,
1312 &info,
1313 &server_major_version,
1314 &server_minor_version);
1315 if (!W_ERROR_IS_OK(werror)) {
1316 continue;
1319 /* need at least one success */
1321 success = true;
1323 printf("\n[%s]\n", archi_table[i].long_archi);
1325 switch (level) {
1326 case 1:
1327 display_print_driver1(&info.info1);
1328 break;
1329 case 2:
1330 display_print_driver2(&info.info2);
1331 break;
1332 case 3:
1333 display_print_driver3(&info.info3);
1334 break;
1335 case 4:
1336 display_print_driver4(&info.info4);
1337 break;
1338 case 5:
1339 display_print_driver5(&info.info5);
1340 break;
1341 case 6:
1342 display_print_driver6(&info.info6);
1343 break;
1344 case 8:
1345 display_print_driver8(&info.info8);
1346 break;
1347 default:
1348 printf("unknown info level %d\n", level);
1349 break;
1353 /* Cleanup */
1355 if (is_valid_policy_hnd(&pol)) {
1356 WERROR _result;
1357 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1360 if (success) {
1361 werror = WERR_OK;
1364 return werror;
1367 /****************************************************************************
1368 ****************************************************************************/
1370 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1371 TALLOC_CTX *mem_ctx,
1372 const char *architecture,
1373 uint32_t level)
1375 WERROR werror;
1376 uint32_t count = 0;
1377 union spoolss_DriverInfo *info = NULL;
1378 uint32_t j;
1380 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1381 cli->srv_name_slash,
1382 architecture,
1383 level,
1385 &count,
1386 &info);
1388 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1389 printf("Server does not support environment [%s]\n",
1390 architecture);
1391 return WERR_OK;
1394 if (count == 0) {
1395 return WERR_OK;
1398 if (!W_ERROR_IS_OK(werror)) {
1399 printf("Error getting driver for environment [%s] - %s\n",
1400 architecture, win_errstr(werror));
1401 return werror;
1404 printf("\n[%s]\n", architecture);
1406 switch (level) {
1407 case 1:
1408 for (j=0; j < count; j++) {
1409 display_print_driver1(&info[j].info1);
1411 break;
1412 case 2:
1413 for (j=0; j < count; j++) {
1414 display_print_driver2(&info[j].info2);
1416 break;
1417 case 3:
1418 for (j=0; j < count; j++) {
1419 display_print_driver3(&info[j].info3);
1421 break;
1422 case 4:
1423 for (j=0; j < count; j++) {
1424 display_print_driver4(&info[j].info4);
1426 break;
1427 case 5:
1428 for (j=0; j < count; j++) {
1429 display_print_driver5(&info[j].info5);
1431 break;
1432 case 6:
1433 for (j=0; j < count; j++) {
1434 display_print_driver6(&info[j].info6);
1436 break;
1437 case 8:
1438 for (j=0; j < count; j++) {
1439 display_print_driver8(&info[j].info8);
1441 break;
1442 default:
1443 printf("unknown info level %d\n", level);
1444 return WERR_UNKNOWN_LEVEL;
1447 return werror;
1450 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1451 TALLOC_CTX *mem_ctx,
1452 int argc, const char **argv)
1454 WERROR werror = WERR_OK;
1455 uint32_t level = 1;
1456 uint32_t i;
1457 const char *architecture = NULL;
1459 if (argc > 3) {
1460 printf("Usage: enumdrivers [level] [architecture]\n");
1461 return WERR_OK;
1464 if (argc >= 2) {
1465 level = atoi(argv[1]);
1468 if (argc == 3) {
1469 architecture = argv[2];
1472 if (architecture) {
1473 return enum_driver_by_architecture(cli, mem_ctx,
1474 architecture,
1475 level);
1478 /* loop through and print driver info level for each architecture */
1479 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1480 /* check to see if we already asked for this architecture string */
1482 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1483 continue;
1486 werror = enum_driver_by_architecture(cli, mem_ctx,
1487 archi_table[i].long_archi,
1488 level);
1489 if (!W_ERROR_IS_OK(werror)) {
1490 break;
1494 return werror;
1497 /****************************************************************************
1498 ****************************************************************************/
1500 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1502 printf("\tDirectory Name:[%s]\n", r->directory_name);
1505 /****************************************************************************
1506 ****************************************************************************/
1508 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1509 TALLOC_CTX *mem_ctx,
1510 int argc, const char **argv)
1512 WERROR result;
1513 NTSTATUS status;
1514 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1515 DATA_BLOB buffer;
1516 uint32_t offered;
1517 union spoolss_DriverDirectoryInfo info;
1518 uint32_t needed;
1519 struct dcerpc_binding_handle *b = cli->binding_handle;
1521 if (argc > 2) {
1522 printf("Usage: %s [environment]\n", argv[0]);
1523 return WERR_OK;
1526 /* Get the arguments need to open the printer handle */
1528 if (argc == 2) {
1529 env = argv[1];
1532 /* Get the directory. Only use Info level 1 */
1534 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1535 cli->srv_name_slash,
1536 env,
1538 NULL, /* buffer */
1539 0, /* offered */
1540 NULL, /* info */
1541 &needed,
1542 &result);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 return ntstatus_to_werror(status);
1546 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1547 offered = needed;
1548 buffer = data_blob_talloc_zero(mem_ctx, needed);
1550 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1551 cli->srv_name_slash,
1552 env,
1554 &buffer,
1555 offered,
1556 &info,
1557 &needed,
1558 &result);
1559 if (!NT_STATUS_IS_OK(status)) {
1560 return ntstatus_to_werror(status);
1564 if (W_ERROR_IS_OK(result)) {
1565 display_printdriverdir_1(&info.info1);
1568 return result;
1571 /****************************************************************************
1572 ****************************************************************************/
1574 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1575 struct spoolss_AddDriverInfo3 *info,
1576 const char *arch)
1579 int i;
1581 for (i=0; archi_table[i].long_archi != NULL; i++)
1583 if (strcmp(arch, archi_table[i].short_archi) == 0)
1585 info->version = archi_table[i].version;
1586 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1587 break;
1591 if (archi_table[i].long_archi == NULL)
1593 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1596 return;
1600 /**************************************************************************
1601 wrapper for strtok to get the next parameter from a delimited list.
1602 Needed to handle the empty parameter string denoted by "NULL"
1603 *************************************************************************/
1605 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1606 const char *delim, const char **dest,
1607 char **saveptr)
1609 char *ptr;
1611 /* get the next token */
1612 ptr = strtok_r(str, delim, saveptr);
1614 /* a string of 'NULL' is used to represent an empty
1615 parameter because two consecutive delimiters
1616 will not return an empty string. See man strtok(3)
1617 for details */
1618 if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1619 ptr = NULL;
1622 if (dest != NULL) {
1623 *dest = talloc_strdup(mem_ctx, ptr);
1626 return ptr;
1629 /********************************************************************************
1630 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1631 string in the form of
1632 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1633 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1634 <Default Data Type>:<Comma Separated list of Files>
1635 *******************************************************************************/
1637 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1638 char *args)
1640 char *str, *str2;
1641 int count = 0;
1642 char *saveptr = NULL;
1643 struct spoolss_StringArray *deps;
1644 const char **file_array = NULL;
1645 int i;
1647 /* fill in the UNISTR fields */
1648 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1649 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1650 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1651 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1652 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1653 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1654 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1656 /* <Comma Separated List of Dependent Files> */
1657 /* save the beginning of the string */
1658 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1659 str = str2;
1661 /* begin to strip out each filename */
1662 str = strtok_r(str, ",", &saveptr);
1664 /* no dependent files, we are done */
1665 if (!str) {
1666 return true;
1669 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1670 if (!deps) {
1671 return false;
1674 while (str != NULL) {
1675 add_string_to_array(deps, str, &file_array, &count);
1676 str = strtok_r(NULL, ",", &saveptr);
1679 deps->string = talloc_zero_array(deps, const char *, count + 1);
1680 if (!deps->string) {
1681 return false;
1684 for (i=0; i < count; i++) {
1685 deps->string[i] = file_array[i];
1688 r->dependent_files = deps;
1690 return true;
1693 /****************************************************************************
1694 ****************************************************************************/
1696 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1697 TALLOC_CTX *mem_ctx,
1698 int argc, const char **argv)
1700 WERROR result;
1701 NTSTATUS status;
1702 uint32_t level = 3;
1703 struct spoolss_AddDriverInfoCtr info_ctr;
1704 struct spoolss_AddDriverInfo3 info3;
1705 const char *arch;
1706 char *driver_args;
1707 struct dcerpc_binding_handle *b = cli->binding_handle;
1709 /* parse the command arguments */
1710 if (argc != 3 && argc != 4)
1712 printf ("Usage: %s <Environment> \\\n", argv[0]);
1713 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1714 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1715 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1716 printf ("\t[version]\n");
1718 return WERR_OK;
1721 /* Fill in the spoolss_AddDriverInfo3 struct */
1722 ZERO_STRUCT(info3);
1724 arch = cmd_spoolss_get_short_archi(argv[1]);
1725 if (!arch) {
1726 printf ("Error Unknown architecture [%s]\n", argv[1]);
1727 return WERR_INVALID_PARAM;
1730 set_drv_info_3_env(mem_ctx, &info3, arch);
1732 driver_args = talloc_strdup( mem_ctx, argv[2] );
1733 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1735 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1736 return WERR_INVALID_PARAM;
1739 /* if printer driver version specified, override the default version
1740 * used by the architecture. This allows installation of Windows
1741 * 2000 (version 3) printer drivers. */
1742 if (argc == 4)
1744 info3.version = atoi(argv[3]);
1748 info_ctr.level = level;
1749 info_ctr.info.info3 = &info3;
1751 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1752 cli->srv_name_slash,
1753 &info_ctr,
1754 &result);
1755 if (!NT_STATUS_IS_OK(status)) {
1756 return ntstatus_to_werror(status);
1758 if (W_ERROR_IS_OK(result)) {
1759 printf ("Printer Driver %s successfully installed.\n",
1760 info3.driver_name);
1763 return result;
1767 /****************************************************************************
1768 ****************************************************************************/
1770 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1771 TALLOC_CTX *mem_ctx,
1772 int argc, const char **argv)
1774 WERROR result;
1775 struct spoolss_SetPrinterInfoCtr info_ctr;
1776 struct spoolss_SetPrinterInfo2 info2;
1778 /* parse the command arguments */
1779 if (argc != 5)
1781 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1782 return WERR_OK;
1785 /* Fill in the DRIVER_INFO_2 struct */
1786 ZERO_STRUCT(info2);
1788 info2.printername = argv[1];
1789 info2.drivername = argv[3];
1790 info2.sharename = argv[2];
1791 info2.portname = argv[4];
1792 info2.comment = "Created by rpcclient";
1793 info2.printprocessor = "winprint";
1794 info2.datatype = "RAW";
1795 info2.devmode_ptr = 0;
1796 info2.secdesc_ptr = 0;
1797 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1798 info2.priority = 0;
1799 info2.defaultpriority = 0;
1800 info2.starttime = 0;
1801 info2.untiltime = 0;
1803 /* These three fields must not be used by AddPrinter()
1804 as defined in the MS Platform SDK documentation..
1805 --jerry
1806 info2.status = 0;
1807 info2.cjobs = 0;
1808 info2.averageppm = 0;
1811 info_ctr.level = 2;
1812 info_ctr.info.info2 = &info2;
1814 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1815 &info_ctr);
1816 if (W_ERROR_IS_OK(result))
1817 printf ("Printer %s successfully installed.\n", argv[1]);
1819 return result;
1822 /****************************************************************************
1823 ****************************************************************************/
1825 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1826 TALLOC_CTX *mem_ctx,
1827 int argc, const char **argv)
1829 struct policy_handle pol;
1830 WERROR result;
1831 NTSTATUS status;
1832 uint32_t level = 2;
1833 const char *printername;
1834 union spoolss_PrinterInfo info;
1835 struct spoolss_SetPrinterInfoCtr info_ctr;
1836 struct spoolss_SetPrinterInfo2 info2;
1837 struct spoolss_DevmodeContainer devmode_ctr;
1838 struct sec_desc_buf secdesc_ctr;
1839 struct dcerpc_binding_handle *b = cli->binding_handle;
1841 ZERO_STRUCT(devmode_ctr);
1842 ZERO_STRUCT(secdesc_ctr);
1844 /* parse the command arguments */
1845 if (argc != 3)
1847 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1848 return WERR_OK;
1851 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1853 /* Get a printer handle */
1855 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1856 printername,
1857 PRINTER_ALL_ACCESS,
1858 &pol);
1859 if (!W_ERROR_IS_OK(result))
1860 goto done;
1862 /* Get printer info */
1864 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1865 &pol,
1866 level,
1868 &info);
1869 if (!W_ERROR_IS_OK(result)) {
1870 printf ("Unable to retrieve printer information!\n");
1871 goto done;
1874 /* Set the printer driver */
1876 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1877 info2.drivername = argv[2];
1879 info_ctr.level = 2;
1880 info_ctr.info.info2 = &info2;
1882 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1883 &pol,
1884 &info_ctr,
1885 &devmode_ctr,
1886 &secdesc_ctr,
1887 0, /* command */
1888 &result);
1889 if (!NT_STATUS_IS_OK(status)) {
1890 result = ntstatus_to_werror(status);
1891 goto done;
1893 if (!W_ERROR_IS_OK(result)) {
1894 printf("SetPrinter call failed!\n");
1895 goto done;
1898 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1900 done:
1901 /* Cleanup */
1903 if (is_valid_policy_hnd(&pol)) {
1904 WERROR _result;
1905 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1908 return result;
1912 /****************************************************************************
1913 ****************************************************************************/
1915 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1916 TALLOC_CTX *mem_ctx,
1917 int argc, const char **argv)
1919 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1920 NTSTATUS status;
1921 struct dcerpc_binding_handle *b = cli->binding_handle;
1923 int i;
1924 int vers = -1;
1926 const char *arch = NULL;
1927 uint32_t delete_flags = 0;
1929 /* parse the command arguments */
1930 if (argc < 2 || argc > 5) {
1931 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
1932 return WERR_OK;
1935 if (argc >= 3)
1936 arch = argv[2];
1937 if (argc >= 4) {
1938 vers = atoi(argv[3]);
1939 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1941 if (argc == 5)
1942 delete_flags = atoi(argv[4]);
1944 /* delete the driver for all architectures */
1945 for (i=0; archi_table[i].long_archi; i++) {
1947 if (arch && !strequal(archi_table[i].long_archi, arch))
1948 continue;
1950 if (vers >= 0 && archi_table[i].version != vers)
1951 continue;
1953 /* make the call to remove the driver */
1954 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1955 cli->srv_name_slash,
1956 archi_table[i].long_archi,
1957 argv[1],
1958 delete_flags,
1959 archi_table[i].version,
1960 &result);
1961 if (!NT_STATUS_IS_OK(status)) {
1962 return ntstatus_to_werror(status);
1964 if ( !W_ERROR_IS_OK(result) )
1966 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1967 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1968 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1971 else
1973 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1974 archi_table[i].long_archi, archi_table[i].version);
1975 ret = WERR_OK;
1979 return ret;
1983 /****************************************************************************
1984 ****************************************************************************/
1986 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1987 TALLOC_CTX *mem_ctx,
1988 int argc, const char **argv)
1990 WERROR result = WERR_OK;
1991 NTSTATUS status;
1992 int i;
1993 struct dcerpc_binding_handle *b = cli->binding_handle;
1995 /* parse the command arguments */
1996 if (argc != 2) {
1997 printf ("Usage: %s <driver>\n", argv[0]);
1998 return WERR_OK;
2001 /* delete the driver for all architectures */
2002 for (i=0; archi_table[i].long_archi; i++) {
2003 result = WERR_OK;
2005 /* make the call to remove the driver */
2006 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2007 cli->srv_name_slash,
2008 archi_table[i].long_archi,
2009 argv[1],
2010 &result);
2011 if (!NT_STATUS_IS_OK(status)) {
2012 result = ntstatus_to_werror(status);
2013 continue;
2015 if ( !W_ERROR_IS_OK(result) ) {
2016 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2017 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2018 argv[1], archi_table[i].long_archi,
2019 win_errstr(result));
2021 } else {
2022 printf ("Driver %s removed for arch [%s].\n", argv[1],
2023 archi_table[i].long_archi);
2027 return result;
2030 /****************************************************************************
2031 ****************************************************************************/
2033 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2034 TALLOC_CTX *mem_ctx,
2035 int argc, const char **argv)
2037 WERROR result;
2038 NTSTATUS status;
2039 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2040 DATA_BLOB buffer;
2041 uint32_t offered;
2042 union spoolss_PrintProcessorDirectoryInfo info;
2043 uint32_t needed;
2044 struct dcerpc_binding_handle *b = cli->binding_handle;
2046 /* parse the command arguments */
2047 if (argc > 2) {
2048 printf ("Usage: %s [environment]\n", argv[0]);
2049 return WERR_OK;
2052 if (argc == 2) {
2053 environment = argv[1];
2056 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2057 cli->srv_name_slash,
2058 environment,
2060 NULL, /* buffer */
2061 0, /* offered */
2062 NULL, /* info */
2063 &needed,
2064 &result);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 return ntstatus_to_werror(status);
2068 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2069 offered = needed;
2070 buffer = data_blob_talloc_zero(mem_ctx, needed);
2072 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2073 cli->srv_name_slash,
2074 environment,
2076 &buffer,
2077 offered,
2078 &info,
2079 &needed,
2080 &result);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 return ntstatus_to_werror(status);
2086 if (W_ERROR_IS_OK(result)) {
2087 printf("%s\n", info.info1.directory_name);
2090 return result;
2093 /****************************************************************************
2094 ****************************************************************************/
2096 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2097 int argc, const char **argv)
2099 struct policy_handle handle;
2100 WERROR werror;
2101 NTSTATUS status;
2102 const char *printername;
2103 union spoolss_AddFormInfo info;
2104 struct spoolss_AddFormInfo1 info1;
2105 struct spoolss_AddFormInfo2 info2;
2106 uint32_t level = 1;
2107 struct dcerpc_binding_handle *b = cli->binding_handle;
2109 /* Parse the command arguments */
2111 if (argc < 3 || argc > 5) {
2112 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2113 return WERR_OK;
2116 /* Get a printer handle */
2118 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2120 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2121 printername,
2122 PRINTER_ALL_ACCESS,
2123 &handle);
2124 if (!W_ERROR_IS_OK(werror))
2125 goto done;
2127 /* Dummy up some values for the form data */
2129 if (argc == 4) {
2130 level = atoi(argv[3]);
2133 switch (level) {
2134 case 1:
2135 info1.flags = SPOOLSS_FORM_USER;
2136 info1.form_name = argv[2];
2137 info1.size.width = 100;
2138 info1.size.height = 100;
2139 info1.area.left = 0;
2140 info1.area.top = 10;
2141 info1.area.right = 20;
2142 info1.area.bottom = 30;
2144 info.info1 = &info1;
2146 break;
2147 case 2:
2148 info2.flags = SPOOLSS_FORM_USER;
2149 info2.form_name = argv[2];
2150 info2.size.width = 100;
2151 info2.size.height = 100;
2152 info2.area.left = 0;
2153 info2.area.top = 10;
2154 info2.area.right = 20;
2155 info2.area.bottom = 30;
2156 info2.keyword = argv[2];
2157 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2158 info2.mui_dll = NULL;
2159 info2.ressource_id = 0;
2160 info2.display_name = argv[2];
2161 info2.lang_id = 0;
2163 info.info2 = &info2;
2165 break;
2166 default:
2167 werror = WERR_INVALID_PARAM;
2168 goto done;
2171 /* Add the form */
2174 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2175 &handle,
2176 level,
2177 info,
2178 &werror);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 werror = ntstatus_to_werror(status);
2181 goto done;
2183 done:
2184 if (is_valid_policy_hnd(&handle)) {
2185 WERROR _result;
2186 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2189 return werror;
2192 /****************************************************************************
2193 ****************************************************************************/
2195 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2196 int argc, const char **argv)
2198 struct policy_handle handle;
2199 WERROR werror;
2200 NTSTATUS status;
2201 const char *printername;
2202 union spoolss_AddFormInfo info;
2203 struct spoolss_AddFormInfo1 info1;
2204 struct dcerpc_binding_handle *b = cli->binding_handle;
2206 /* Parse the command arguments */
2208 if (argc != 3) {
2209 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2210 return WERR_OK;
2213 /* Get a printer handle */
2215 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2217 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2218 printername,
2219 SEC_FLAG_MAXIMUM_ALLOWED,
2220 &handle);
2221 if (!W_ERROR_IS_OK(werror))
2222 goto done;
2224 /* Dummy up some values for the form data */
2226 info1.flags = SPOOLSS_FORM_PRINTER;
2227 info1.size.width = 100;
2228 info1.size.height = 100;
2229 info1.area.left = 0;
2230 info1.area.top = 1000;
2231 info1.area.right = 2000;
2232 info1.area.bottom = 3000;
2233 info1.form_name = argv[2];
2235 info.info1 = &info1;
2237 /* Set the form */
2239 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2240 &handle,
2241 argv[2],
2243 info,
2244 &werror);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 werror = ntstatus_to_werror(status);
2247 goto done;
2249 done:
2250 if (is_valid_policy_hnd(&handle)) {
2251 WERROR _result;
2252 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2255 return werror;
2258 /****************************************************************************
2259 ****************************************************************************/
2261 static const char *get_form_flag(int form_flag)
2263 switch (form_flag) {
2264 case SPOOLSS_FORM_USER:
2265 return "FORM_USER";
2266 case SPOOLSS_FORM_BUILTIN:
2267 return "FORM_BUILTIN";
2268 case SPOOLSS_FORM_PRINTER:
2269 return "FORM_PRINTER";
2270 default:
2271 return "unknown";
2275 /****************************************************************************
2276 ****************************************************************************/
2278 static void display_form_info1(struct spoolss_FormInfo1 *r)
2280 printf("%s\n" \
2281 "\tflag: %s (%d)\n" \
2282 "\twidth: %d, length: %d\n" \
2283 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2284 r->form_name, get_form_flag(r->flags), r->flags,
2285 r->size.width, r->size.height,
2286 r->area.left, r->area.right,
2287 r->area.top, r->area.bottom);
2290 /****************************************************************************
2291 ****************************************************************************/
2293 static void display_form_info2(struct spoolss_FormInfo2 *r)
2295 printf("%s\n" \
2296 "\tflag: %s (%d)\n" \
2297 "\twidth: %d, length: %d\n" \
2298 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2299 r->form_name, get_form_flag(r->flags), r->flags,
2300 r->size.width, r->size.height,
2301 r->area.left, r->area.right,
2302 r->area.top, r->area.bottom);
2303 printf("\tkeyword: %s\n", r->keyword);
2304 printf("\tstring_type: 0x%08x\n", r->string_type);
2305 printf("\tmui_dll: %s\n", r->mui_dll);
2306 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2307 printf("\tdisplay_name: %s\n", r->display_name);
2308 printf("\tlang_id: %d\n", r->lang_id);
2309 printf("\n");
2312 /****************************************************************************
2313 ****************************************************************************/
2315 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2316 int argc, const char **argv)
2318 struct policy_handle handle;
2319 WERROR werror;
2320 NTSTATUS status;
2321 const char *printername;
2322 DATA_BLOB buffer;
2323 uint32_t offered = 0;
2324 union spoolss_FormInfo info;
2325 uint32_t needed;
2326 uint32_t level = 1;
2327 struct dcerpc_binding_handle *b = cli->binding_handle;
2329 /* Parse the command arguments */
2331 if (argc < 3 || argc > 5) {
2332 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2333 return WERR_OK;
2336 /* Get a printer handle */
2338 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2340 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2341 printername,
2342 SEC_FLAG_MAXIMUM_ALLOWED,
2343 &handle);
2344 if (!W_ERROR_IS_OK(werror))
2345 goto done;
2347 if (argc == 4) {
2348 level = atoi(argv[3]);
2351 /* Get the form */
2353 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2354 &handle,
2355 argv[2],
2356 level,
2357 NULL,
2358 offered,
2359 &info,
2360 &needed,
2361 &werror);
2362 if (!NT_STATUS_IS_OK(status)) {
2363 werror = ntstatus_to_werror(status);
2364 goto done;
2366 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2367 buffer = data_blob_talloc_zero(mem_ctx, needed);
2368 offered = needed;
2369 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2370 &handle,
2371 argv[2],
2372 level,
2373 &buffer,
2374 offered,
2375 &info,
2376 &needed,
2377 &werror);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 werror = ntstatus_to_werror(status);
2380 goto done;
2384 if (!W_ERROR_IS_OK(werror)) {
2385 goto done;
2388 switch (level) {
2389 case 1:
2390 display_form_info1(&info.info1);
2391 break;
2392 case 2:
2393 display_form_info2(&info.info2);
2394 break;
2397 done:
2398 if (is_valid_policy_hnd(&handle)) {
2399 WERROR _result;
2400 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2403 return werror;
2406 /****************************************************************************
2407 ****************************************************************************/
2409 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2410 TALLOC_CTX *mem_ctx, int argc,
2411 const char **argv)
2413 struct policy_handle handle;
2414 WERROR werror;
2415 NTSTATUS status;
2416 const char *printername;
2417 struct dcerpc_binding_handle *b = cli->binding_handle;
2419 /* Parse the command arguments */
2421 if (argc != 3) {
2422 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2423 return WERR_OK;
2426 /* Get a printer handle */
2428 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2430 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2431 printername,
2432 SEC_FLAG_MAXIMUM_ALLOWED,
2433 &handle);
2434 if (!W_ERROR_IS_OK(werror))
2435 goto done;
2437 /* Delete the form */
2439 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2440 &handle,
2441 argv[2],
2442 &werror);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 werror = ntstatus_to_werror(status);
2445 goto done;
2448 done:
2449 if (is_valid_policy_hnd(&handle)) {
2450 WERROR _result;
2451 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2454 return werror;
2457 /****************************************************************************
2458 ****************************************************************************/
2460 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2461 TALLOC_CTX *mem_ctx, int argc,
2462 const char **argv)
2464 struct policy_handle handle;
2465 WERROR werror;
2466 const char *printername;
2467 uint32_t num_forms, level = 1, i;
2468 union spoolss_FormInfo *forms;
2469 struct dcerpc_binding_handle *b = cli->binding_handle;
2471 /* Parse the command arguments */
2473 if (argc < 2 || argc > 4) {
2474 printf ("Usage: %s <printer> [level]\n", argv[0]);
2475 return WERR_OK;
2478 /* Get a printer handle */
2480 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2482 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2483 printername,
2484 SEC_FLAG_MAXIMUM_ALLOWED,
2485 &handle);
2486 if (!W_ERROR_IS_OK(werror))
2487 goto done;
2489 if (argc == 3) {
2490 level = atoi(argv[2]);
2493 /* Enumerate forms */
2495 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2496 &handle,
2497 level,
2499 &num_forms,
2500 &forms);
2502 if (!W_ERROR_IS_OK(werror))
2503 goto done;
2505 /* Display output */
2507 for (i = 0; i < num_forms; i++) {
2508 switch (level) {
2509 case 1:
2510 display_form_info1(&forms[i].info1);
2511 break;
2512 case 2:
2513 display_form_info2(&forms[i].info2);
2514 break;
2518 done:
2519 if (is_valid_policy_hnd(&handle)) {
2520 WERROR _result;
2521 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2524 return werror;
2527 /****************************************************************************
2528 ****************************************************************************/
2530 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2531 TALLOC_CTX *mem_ctx,
2532 int argc, const char **argv)
2534 WERROR result;
2535 NTSTATUS status;
2536 const char *printername;
2537 struct policy_handle pol = { 0, };
2538 union spoolss_PrinterInfo info;
2539 enum winreg_Type type;
2540 union spoolss_PrinterData data;
2541 DATA_BLOB blob;
2542 struct dcerpc_binding_handle *b = cli->binding_handle;
2544 /* parse the command arguments */
2545 if (argc < 5) {
2546 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2547 " <value> <data>\n",
2548 argv[0]);
2549 return WERR_OK;
2552 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2554 type = REG_NONE;
2556 if (strequal(argv[2], "string")) {
2557 type = REG_SZ;
2560 if (strequal(argv[2], "binary")) {
2561 type = REG_BINARY;
2564 if (strequal(argv[2], "dword")) {
2565 type = REG_DWORD;
2568 if (strequal(argv[2], "multistring")) {
2569 type = REG_MULTI_SZ;
2572 if (type == REG_NONE) {
2573 printf("Unknown data type: %s\n", argv[2]);
2574 result = WERR_INVALID_PARAM;
2575 goto done;
2578 /* get a printer handle */
2580 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2581 printername,
2582 SEC_FLAG_MAXIMUM_ALLOWED,
2583 &pol);
2584 if (!W_ERROR_IS_OK(result)) {
2585 goto done;
2588 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2589 &pol,
2592 &info);
2593 if (!W_ERROR_IS_OK(result)) {
2594 goto done;
2597 printf("%s\n", current_timestring(mem_ctx, true));
2598 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2600 /* Set the printer data */
2602 switch (type) {
2603 case REG_SZ:
2604 data.string = talloc_strdup(mem_ctx, argv[4]);
2605 W_ERROR_HAVE_NO_MEMORY(data.string);
2606 break;
2607 case REG_DWORD:
2608 data.value = strtoul(argv[4], NULL, 10);
2609 break;
2610 case REG_BINARY:
2611 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2612 break;
2613 case REG_MULTI_SZ: {
2614 int i, num_strings;
2615 const char **strings = NULL;
2617 num_strings = 0;
2619 for (i=4; i<argc; i++) {
2620 if (strcmp(argv[i], "NULL") == 0) {
2621 argv[i] = "";
2623 if (!add_string_to_array(mem_ctx, argv[i],
2624 &strings,
2625 &num_strings)) {
2626 result = WERR_NOMEM;
2627 goto done;
2630 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2631 if (!data.string_array) {
2632 result = WERR_NOMEM;
2633 goto done;
2635 for (i=0; i < num_strings; i++) {
2636 data.string_array[i] = strings[i];
2638 break;
2640 default:
2641 printf("Unknown data type: %s\n", argv[2]);
2642 result = WERR_INVALID_PARAM;
2643 goto done;
2646 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2647 if (!W_ERROR_IS_OK(result)) {
2648 goto done;
2651 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2652 &pol,
2653 argv[3], /* value_name */
2654 type,
2655 blob.data,
2656 blob.length,
2657 &result);
2658 if (!NT_STATUS_IS_OK(status)) {
2659 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2660 result = ntstatus_to_werror(status);
2661 goto done;
2663 if (!W_ERROR_IS_OK(result)) {
2664 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2665 goto done;
2667 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2669 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2670 &pol,
2673 &info);
2674 if (!W_ERROR_IS_OK(result)) {
2675 goto done;
2678 printf("%s\n", current_timestring(mem_ctx, true));
2679 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2681 done:
2682 /* cleanup */
2683 if (is_valid_policy_hnd(&pol)) {
2684 WERROR _result;
2685 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2688 return result;
2691 /****************************************************************************
2692 ****************************************************************************/
2694 static void display_job_info1(struct spoolss_JobInfo1 *r)
2696 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2697 r->user_name, r->document_name, r->text_status, r->pages_printed,
2698 r->total_pages);
2701 /****************************************************************************
2702 ****************************************************************************/
2704 static void display_job_info2(struct spoolss_JobInfo2 *r)
2706 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2707 r->position, r->job_id,
2708 r->user_name, r->document_name, r->text_status, r->pages_printed,
2709 r->total_pages, r->size);
2712 /****************************************************************************
2713 ****************************************************************************/
2715 static void display_job_info3(struct spoolss_JobInfo3 *r)
2717 printf("jobid[%d], next_jobid[%d]\n",
2718 r->job_id, r->next_job_id);
2721 /****************************************************************************
2722 ****************************************************************************/
2724 static void display_job_info4(struct spoolss_JobInfo4 *r)
2726 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2727 r->position, r->job_id,
2728 r->user_name, r->document_name, r->text_status, r->pages_printed,
2729 r->total_pages, r->size, r->size_high);
2732 /****************************************************************************
2733 ****************************************************************************/
2735 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2736 TALLOC_CTX *mem_ctx, int argc,
2737 const char **argv)
2739 WERROR result;
2740 uint32_t level = 1, count, i;
2741 const char *printername;
2742 struct policy_handle hnd;
2743 union spoolss_JobInfo *info;
2744 struct dcerpc_binding_handle *b = cli->binding_handle;
2746 if (argc < 2 || argc > 3) {
2747 printf("Usage: %s printername [level]\n", argv[0]);
2748 return WERR_OK;
2751 if (argc == 3) {
2752 level = atoi(argv[2]);
2755 /* Open printer handle */
2757 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2759 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2760 printername,
2761 SEC_FLAG_MAXIMUM_ALLOWED,
2762 &hnd);
2763 if (!W_ERROR_IS_OK(result))
2764 goto done;
2766 /* Enumerate ports */
2768 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2769 &hnd,
2770 0, /* firstjob */
2771 1000, /* numjobs */
2772 level,
2774 &count,
2775 &info);
2776 if (!W_ERROR_IS_OK(result)) {
2777 goto done;
2780 for (i = 0; i < count; i++) {
2781 switch (level) {
2782 case 1:
2783 display_job_info1(&info[i].info1);
2784 break;
2785 case 2:
2786 display_job_info2(&info[i].info2);
2787 break;
2788 default:
2789 d_printf("unknown info level %d\n", level);
2790 break;
2794 done:
2795 if (is_valid_policy_hnd(&hnd)) {
2796 WERROR _result;
2797 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2800 return result;
2803 /****************************************************************************
2804 ****************************************************************************/
2806 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2807 TALLOC_CTX *mem_ctx, int argc,
2808 const char **argv)
2810 WERROR result;
2811 const char *printername;
2812 struct policy_handle hnd;
2813 uint32_t job_id;
2814 uint32_t level = 1;
2815 union spoolss_JobInfo info;
2816 struct dcerpc_binding_handle *b = cli->binding_handle;
2818 if (argc < 3 || argc > 4) {
2819 printf("Usage: %s printername job_id [level]\n", argv[0]);
2820 return WERR_OK;
2823 job_id = atoi(argv[2]);
2825 if (argc == 4) {
2826 level = atoi(argv[3]);
2829 /* Open printer handle */
2831 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2833 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2834 printername,
2835 SEC_FLAG_MAXIMUM_ALLOWED,
2836 &hnd);
2837 if (!W_ERROR_IS_OK(result)) {
2838 goto done;
2841 /* Enumerate ports */
2843 result = rpccli_spoolss_getjob(cli, mem_ctx,
2844 &hnd,
2845 job_id,
2846 level,
2848 &info);
2850 if (!W_ERROR_IS_OK(result)) {
2851 goto done;
2854 switch (level) {
2855 case 1:
2856 display_job_info1(&info.info1);
2857 break;
2858 case 2:
2859 display_job_info2(&info.info2);
2860 break;
2861 case 3:
2862 display_job_info3(&info.info3);
2863 break;
2864 case 4:
2865 display_job_info4(&info.info4);
2866 break;
2867 default:
2868 d_printf("unknown info level %d\n", level);
2869 break;
2872 done:
2873 if (is_valid_policy_hnd(&hnd)) {
2874 WERROR _result;
2875 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2878 return result;
2881 /****************************************************************************
2882 ****************************************************************************/
2884 static struct {
2885 const char *name;
2886 enum spoolss_JobControl val;
2887 } cmdvals[] = {
2888 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2889 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2890 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2891 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2892 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2893 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2894 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2895 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2896 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2899 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2901 int i;
2903 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2904 if (strequal(cmdvals[i].name, cmd)) {
2905 return cmdvals[i].val;
2908 return (enum spoolss_JobControl)atoi(cmd);
2911 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2912 TALLOC_CTX *mem_ctx, int argc,
2913 const char **argv)
2915 WERROR result;
2916 NTSTATUS status;
2917 const char *printername;
2918 struct policy_handle hnd;
2919 uint32_t job_id;
2920 enum spoolss_JobControl command;
2921 struct dcerpc_binding_handle *b = cli->binding_handle;
2923 if (argc != 4) {
2924 printf("Usage: %s printername job_id command\n", argv[0]);
2925 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2926 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2927 return WERR_OK;
2930 job_id = atoi(argv[2]);
2931 command = parse_setjob_command(argv[3]);
2933 /* Open printer handle */
2935 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2937 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2938 printername,
2939 SEC_FLAG_MAXIMUM_ALLOWED,
2940 &hnd);
2941 if (!W_ERROR_IS_OK(result)) {
2942 goto done;
2945 /* Set Job */
2947 status = dcerpc_spoolss_SetJob(b, mem_ctx,
2948 &hnd,
2949 job_id,
2950 NULL,
2951 command,
2952 &result);
2953 if (!NT_STATUS_IS_OK(status)) {
2954 result = ntstatus_to_werror(status);
2955 goto done;
2957 if (!W_ERROR_IS_OK(result)) {
2958 goto done;
2961 done:
2962 if (is_valid_policy_hnd(&hnd)) {
2963 WERROR _result;
2964 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2967 return result;
2970 /****************************************************************************
2971 ****************************************************************************/
2973 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2974 TALLOC_CTX *mem_ctx, int argc,
2975 const char **argv)
2977 WERROR result;
2978 NTSTATUS status;
2979 const char *printername;
2980 struct policy_handle hnd;
2981 uint32_t value_needed;
2982 enum winreg_Type type;
2983 uint32_t data_needed;
2984 struct dcerpc_binding_handle *b = cli->binding_handle;
2985 struct spoolss_EnumPrinterData r;
2987 if (argc != 2) {
2988 printf("Usage: %s printername\n", argv[0]);
2989 return WERR_OK;
2992 /* Open printer handle */
2994 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2996 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2997 printername,
2998 SEC_FLAG_MAXIMUM_ALLOWED,
2999 &hnd);
3000 if (!W_ERROR_IS_OK(result)) {
3001 goto done;
3004 /* Enumerate data */
3006 r.in.handle = &hnd;
3007 r.in.enum_index = 0;
3008 r.in.value_offered = 0;
3009 r.in.data_offered = 0;
3010 r.out.value_name = NULL;
3011 r.out.value_needed = &value_needed;
3012 r.out.type = &type;
3013 r.out.data = NULL;
3014 r.out.data_needed = &data_needed;
3016 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3017 if (!NT_STATUS_IS_OK(status)) {
3018 result = ntstatus_to_werror(status);
3019 goto done;
3022 if (!W_ERROR_IS_OK(r.out.result)) {
3023 result = r.out.result;
3024 goto done;
3027 r.in.data_offered = *r.out.data_needed;
3028 r.in.value_offered = *r.out.value_needed;
3029 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3030 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3032 do {
3034 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3035 if (!NT_STATUS_IS_OK(status)) {
3036 result = ntstatus_to_werror(status);
3037 goto done;
3040 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3041 result = WERR_OK;
3042 break;
3045 r.in.enum_index++;
3047 display_reg_value(r.out.value_name, *r.out.type,
3048 data_blob_const(r.out.data, r.in.data_offered));
3050 } while (W_ERROR_IS_OK(r.out.result));
3052 done:
3053 if (is_valid_policy_hnd(&hnd)) {
3054 WERROR _result;
3055 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3058 return result;
3061 /****************************************************************************
3062 ****************************************************************************/
3064 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3065 TALLOC_CTX *mem_ctx, int argc,
3066 const char **argv)
3068 WERROR result;
3069 uint32_t i;
3070 const char *printername;
3071 struct policy_handle hnd;
3072 uint32_t count;
3073 struct spoolss_PrinterEnumValues *info;
3074 struct dcerpc_binding_handle *b = cli->binding_handle;
3076 if (argc != 3) {
3077 printf("Usage: %s printername <keyname>\n", argv[0]);
3078 return WERR_OK;
3081 /* Open printer handle */
3083 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3085 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3086 printername,
3087 SEC_FLAG_MAXIMUM_ALLOWED,
3088 &hnd);
3089 if (!W_ERROR_IS_OK(result)) {
3090 goto done;
3093 /* Enumerate subkeys */
3095 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3096 &hnd,
3097 argv[2],
3099 &count,
3100 &info);
3101 if (!W_ERROR_IS_OK(result)) {
3102 goto done;
3105 for (i=0; i < count; i++) {
3106 display_printer_data(info[i].value_name,
3107 info[i].type,
3108 info[i].data->data,
3109 info[i].data->length);
3112 done:
3113 if (is_valid_policy_hnd(&hnd)) {
3114 WERROR _result;
3115 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3118 return result;
3121 /****************************************************************************
3122 ****************************************************************************/
3124 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3125 TALLOC_CTX *mem_ctx, int argc,
3126 const char **argv)
3128 WERROR result;
3129 const char *printername;
3130 const char *keyname = NULL;
3131 struct policy_handle hnd;
3132 const char **key_buffer = NULL;
3133 int i;
3134 uint32_t offered = 0;
3135 struct dcerpc_binding_handle *b = cli->binding_handle;
3137 if (argc < 2 || argc > 4) {
3138 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3139 return WERR_OK;
3142 if (argc >= 3) {
3143 keyname = argv[2];
3144 } else {
3145 keyname = "";
3148 if (argc == 4) {
3149 offered = atoi(argv[3]);
3152 /* Open printer handle */
3154 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3156 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3157 printername,
3158 SEC_FLAG_MAXIMUM_ALLOWED,
3159 &hnd);
3160 if (!W_ERROR_IS_OK(result)) {
3161 goto done;
3164 /* Enumerate subkeys */
3166 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3167 &hnd,
3168 keyname,
3169 &key_buffer,
3170 offered);
3172 if (!W_ERROR_IS_OK(result)) {
3173 goto done;
3176 for (i=0; key_buffer && key_buffer[i]; i++) {
3177 printf("%s\n", key_buffer[i]);
3180 done:
3182 if (is_valid_policy_hnd(&hnd)) {
3183 WERROR _result;
3184 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3187 return result;
3190 /****************************************************************************
3191 ****************************************************************************/
3193 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3194 TALLOC_CTX *mem_ctx, int argc,
3195 const char **argv)
3197 const char *printername;
3198 const char *clientname;
3199 struct policy_handle hnd = { 0, };
3200 WERROR result;
3201 NTSTATUS status;
3202 struct spoolss_NotifyOption option;
3203 struct dcerpc_binding_handle *b = cli->binding_handle;
3205 if (argc != 2) {
3206 printf("Usage: %s printername\n", argv[0]);
3207 result = WERR_OK;
3208 goto done;
3211 /* Open printer */
3213 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3215 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3216 printername,
3217 SEC_FLAG_MAXIMUM_ALLOWED,
3218 &hnd);
3219 if (!W_ERROR_IS_OK(result)) {
3220 printf("Error opening %s\n", argv[1]);
3221 goto done;
3224 /* Create spool options */
3226 option.version = 2;
3227 option.count = 2;
3229 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3230 if (option.types == NULL) {
3231 result = WERR_NOMEM;
3232 goto done;
3235 option.types[0].type = PRINTER_NOTIFY_TYPE;
3236 option.types[0].count = 1;
3237 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3238 if (option.types[0].fields == NULL) {
3239 result = WERR_NOMEM;
3240 goto done;
3242 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3244 option.types[1].type = JOB_NOTIFY_TYPE;
3245 option.types[1].count = 1;
3246 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3247 if (option.types[1].fields == NULL) {
3248 result = WERR_NOMEM;
3249 goto done;
3251 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3253 clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3254 if (!clientname) {
3255 result = WERR_NOMEM;
3256 goto done;
3259 /* Send rffpcnex */
3261 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3262 &hnd,
3265 clientname,
3266 123,
3267 &option,
3268 &result);
3269 if (!NT_STATUS_IS_OK(status)) {
3270 result = ntstatus_to_werror(status);
3271 goto done;
3273 if (!W_ERROR_IS_OK(result)) {
3274 printf("Error rffpcnex %s\n", argv[1]);
3275 goto done;
3278 done:
3279 if (is_valid_policy_hnd(&hnd)) {
3280 WERROR _result;
3281 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3284 return result;
3287 /****************************************************************************
3288 ****************************************************************************/
3290 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3291 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3293 union spoolss_PrinterInfo info1, info2;
3294 WERROR werror;
3295 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3297 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3298 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3299 hnd1,
3302 &info1);
3303 if ( !W_ERROR_IS_OK(werror) ) {
3304 printf("failed (%s)\n", win_errstr(werror));
3305 talloc_destroy(mem_ctx);
3306 return false;
3308 printf("ok\n");
3310 printf("Retrieving printer properties for %s...", cli2->desthost);
3311 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3312 hnd2,
3315 &info2);
3316 if ( !W_ERROR_IS_OK(werror) ) {
3317 printf("failed (%s)\n", win_errstr(werror));
3318 talloc_destroy(mem_ctx);
3319 return false;
3321 printf("ok\n");
3323 talloc_destroy(mem_ctx);
3325 return true;
3328 /****************************************************************************
3329 ****************************************************************************/
3331 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3332 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3334 union spoolss_PrinterInfo info1, info2;
3335 WERROR werror;
3336 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3337 struct security_descriptor *sd1, *sd2;
3338 bool result = true;
3341 printf("Retrieving printer security for %s...", cli1->desthost);
3342 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3343 hnd1,
3346 &info1);
3347 if ( !W_ERROR_IS_OK(werror) ) {
3348 printf("failed (%s)\n", win_errstr(werror));
3349 result = false;
3350 goto done;
3352 printf("ok\n");
3354 printf("Retrieving printer security for %s...", cli2->desthost);
3355 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3356 hnd2,
3359 &info2);
3360 if ( !W_ERROR_IS_OK(werror) ) {
3361 printf("failed (%s)\n", win_errstr(werror));
3362 result = false;
3363 goto done;
3365 printf("ok\n");
3368 printf("++ ");
3370 sd1 = info1.info3.secdesc;
3371 sd2 = info2.info3.secdesc;
3373 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3374 printf("NULL secdesc!\n");
3375 result = false;
3376 goto done;
3379 if (!security_descriptor_equal( sd1, sd2 ) ) {
3380 printf("Security Descriptors *not* equal!\n");
3381 result = false;
3382 goto done;
3385 printf("Security descriptors match\n");
3387 done:
3388 talloc_destroy(mem_ctx);
3389 return result;
3393 /****************************************************************************
3394 ****************************************************************************/
3396 extern struct user_auth_info *rpcclient_auth_info;
3398 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3399 TALLOC_CTX *mem_ctx, int argc,
3400 const char **argv)
3402 const char *printername;
3403 char *printername_path = NULL;
3404 struct cli_state *cli_server2 = NULL;
3405 struct rpc_pipe_client *cli2 = NULL;
3406 struct policy_handle hPrinter1, hPrinter2;
3407 NTSTATUS nt_status;
3408 WERROR werror;
3410 if ( argc != 3 ) {
3411 printf("Usage: %s <printer> <server>\n", argv[0]);
3412 return WERR_OK;
3415 printername = argv[1];
3417 /* first get the connection to the remote server */
3419 nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
3420 NULL, 0,
3421 "IPC$", "IPC",
3422 get_cmdline_auth_info_username(rpcclient_auth_info),
3423 lp_workgroup(),
3424 get_cmdline_auth_info_password(rpcclient_auth_info),
3425 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3426 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3428 if ( !NT_STATUS_IS_OK(nt_status) )
3429 return WERR_GENERAL_FAILURE;
3431 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3432 &cli2);
3433 if (!NT_STATUS_IS_OK(nt_status)) {
3434 printf("failed to open spoolss pipe on server %s (%s)\n",
3435 argv[2], nt_errstr(nt_status));
3436 return WERR_GENERAL_FAILURE;
3439 /* now open up both printers */
3441 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3443 printf("Opening %s...", printername_path);
3445 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3446 printername_path,
3447 PRINTER_ALL_ACCESS,
3448 &hPrinter1);
3449 if ( !W_ERROR_IS_OK(werror) ) {
3450 printf("failed (%s)\n", win_errstr(werror));
3451 goto done;
3453 printf("ok\n");
3455 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3457 printf("Opening %s...", printername_path);
3458 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3459 printername_path,
3460 PRINTER_ALL_ACCESS,
3461 &hPrinter2);
3462 if ( !W_ERROR_IS_OK(werror) ) {
3463 printf("failed (%s)\n", win_errstr(werror));
3464 goto done;
3466 printf("ok\n");
3468 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3469 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3470 #if 0
3471 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3472 #endif
3475 done:
3476 /* cleanup */
3478 printf("Closing printers...");
3480 WERROR _result;
3481 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3482 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3484 printf("ok\n");
3486 /* close the second remote connection */
3488 cli_shutdown( cli_server2 );
3489 return WERR_OK;
3492 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3494 printf("print_processor_name: %s\n", r->print_processor_name);
3497 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3498 TALLOC_CTX *mem_ctx, int argc,
3499 const char **argv)
3501 WERROR werror;
3502 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3503 uint32_t num_procs, level = 1, i;
3504 union spoolss_PrintProcessorInfo *procs;
3506 /* Parse the command arguments */
3508 if (argc < 1 || argc > 4) {
3509 printf ("Usage: %s [environment] [level]\n", argv[0]);
3510 return WERR_OK;
3513 if (argc >= 2) {
3514 environment = argv[1];
3517 if (argc == 3) {
3518 level = atoi(argv[2]);
3521 /* Enumerate Print Processors */
3523 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3524 cli->srv_name_slash,
3525 environment,
3526 level,
3528 &num_procs,
3529 &procs);
3530 if (!W_ERROR_IS_OK(werror))
3531 goto done;
3533 /* Display output */
3535 for (i = 0; i < num_procs; i++) {
3536 switch (level) {
3537 case 1:
3538 display_proc_info1(&procs[i].info1);
3539 break;
3543 done:
3544 return werror;
3547 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3549 printf("name_array: %s\n", r->name_array);
3552 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3553 TALLOC_CTX *mem_ctx, int argc,
3554 const char **argv)
3556 WERROR werror;
3557 const char *print_processor_name = "winprint";
3558 uint32_t num_procs, level = 1, i;
3559 union spoolss_PrintProcDataTypesInfo *procs;
3561 /* Parse the command arguments */
3563 if (argc < 1 || argc > 4) {
3564 printf ("Usage: %s [environment] [level]\n", argv[0]);
3565 return WERR_OK;
3568 if (argc >= 2) {
3569 print_processor_name = argv[1];
3572 if (argc == 3) {
3573 level = atoi(argv[2]);
3576 /* Enumerate Print Processor Data Types */
3578 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3579 cli->srv_name_slash,
3580 print_processor_name,
3581 level,
3583 &num_procs,
3584 &procs);
3585 if (!W_ERROR_IS_OK(werror))
3586 goto done;
3588 /* Display output */
3590 for (i = 0; i < num_procs; i++) {
3591 switch (level) {
3592 case 1:
3593 display_proc_data_types_info1(&procs[i].info1);
3594 break;
3598 done:
3599 return werror;
3602 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3604 printf("monitor_name: %s\n", r->monitor_name);
3607 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3609 printf("monitor_name: %s\n", r->monitor_name);
3610 printf("environment: %s\n", r->environment);
3611 printf("dll_name: %s\n", r->dll_name);
3614 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3615 TALLOC_CTX *mem_ctx, int argc,
3616 const char **argv)
3618 WERROR werror;
3619 uint32_t count, level = 1, i;
3620 union spoolss_MonitorInfo *info;
3622 /* Parse the command arguments */
3624 if (argc > 2) {
3625 printf("Usage: %s [level]\n", argv[0]);
3626 return WERR_OK;
3629 if (argc == 2) {
3630 level = atoi(argv[1]);
3633 /* Enumerate Print Monitors */
3635 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3636 cli->srv_name_slash,
3637 level,
3639 &count,
3640 &info);
3641 if (!W_ERROR_IS_OK(werror)) {
3642 goto done;
3645 /* Display output */
3647 for (i = 0; i < count; i++) {
3648 switch (level) {
3649 case 1:
3650 display_monitor1(&info[i].info1);
3651 break;
3652 case 2:
3653 display_monitor2(&info[i].info2);
3654 break;
3658 done:
3659 return werror;
3662 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3663 TALLOC_CTX *mem_ctx, int argc,
3664 const char **argv)
3666 WERROR result;
3667 NTSTATUS status;
3668 struct policy_handle handle, gdi_handle;
3669 const char *printername;
3670 struct spoolss_DevmodeContainer devmode_ctr;
3671 struct dcerpc_binding_handle *b = cli->binding_handle;
3673 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3675 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3676 printername,
3677 SEC_FLAG_MAXIMUM_ALLOWED,
3678 &handle);
3679 if (!W_ERROR_IS_OK(result)) {
3680 return result;
3683 ZERO_STRUCT(devmode_ctr);
3685 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3686 &handle,
3687 &gdi_handle,
3688 &devmode_ctr,
3689 &result);
3690 if (!NT_STATUS_IS_OK(status)) {
3691 result = ntstatus_to_werror(status);
3692 goto done;
3694 if (!W_ERROR_IS_OK(result)) {
3695 goto done;
3698 done:
3699 if (is_valid_policy_hnd(&gdi_handle)) {
3700 WERROR _result;
3701 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3703 if (is_valid_policy_hnd(&handle)) {
3704 WERROR _result;
3705 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3708 return result;
3711 /* List of commands exported by this module */
3712 struct cmd_set spoolss_commands[] = {
3714 { "SPOOLSS" },
3716 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss, NULL, "Add a print driver", "" },
3717 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss, NULL, "Add a printer", "" },
3718 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss, NULL, "Delete a printer driver", "" },
3719 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss, NULL, "Delete a printer driver with files", "" },
3720 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss, NULL, "Enumerate printer data", "" },
3721 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss, NULL, "Enumerate printer data for a key", "" },
3722 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss, NULL, "Enumerate printer keys", "" },
3723 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss, NULL, "Enumerate print jobs", "" },
3724 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss, NULL, "Get print job", "" },
3725 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss, NULL, "Set print job", "" },
3726 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss, NULL, "Enumerate printer ports", "" },
3727 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss, NULL, "Enumerate installed printer drivers", "" },
3728 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss, NULL, "Enumerate printers", "" },
3729 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss, NULL, "Get print driver data", "" },
3730 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss, NULL, "Get printer driver data with keyname", ""},
3731 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss, NULL, "Get print driver information", "" },
3732 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss, NULL, "Get print driver upload directory", "" },
3733 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss, NULL, "Get printer info", "" },
3734 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss, NULL, "Open printer handle", "" },
3735 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss, NULL, "Open printer handle", "" },
3736 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss, NULL, "Set printer driver", "" },
3737 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss, NULL, "Get print processor directory", "" },
3738 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss, NULL, "Add form", "" },
3739 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss, NULL, "Set form", "" },
3740 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss, NULL, "Get form", "" },
3741 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss, NULL, "Delete form", "" },
3742 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss, NULL, "Enumerate forms", "" },
3743 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss, NULL, "Set printer comment", "" },
3744 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss, NULL, "Set printername", "" },
3745 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss, NULL, "Set REG_SZ printer data", "" },
3746 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss, NULL, "Rffpcnex test", "" },
3747 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss, NULL, "Printer comparison test", "" },
3748 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss, NULL, "Enumerate Print Processors", "" },
3749 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3750 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss, NULL, "Enumerate Print Monitors", "" },
3751 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss, NULL, "Create Printer IC", "" },
3753 { NULL }