dsdb-acl: give error string if we can not obtain the schema
[Samba/gebeck_regimport.git] / source3 / rpcclient / cmd_spoolss.c
blob52631849e09f6e55fdb98c0629871ca6928a08b8
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 Driver 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 bool ok;
1676 ok = add_string_to_array(deps, str, &file_array, &count);
1677 if (!ok) {
1678 return false;
1680 str = strtok_r(NULL, ",", &saveptr);
1683 deps->string = talloc_zero_array(deps, const char *, count + 1);
1684 if (!deps->string) {
1685 return false;
1688 for (i=0; i < count; i++) {
1689 deps->string[i] = file_array[i];
1692 r->dependent_files = deps;
1694 return true;
1697 /****************************************************************************
1698 ****************************************************************************/
1700 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1701 TALLOC_CTX *mem_ctx,
1702 int argc, const char **argv)
1704 WERROR result;
1705 NTSTATUS status;
1706 uint32_t level = 3;
1707 struct spoolss_AddDriverInfoCtr info_ctr;
1708 struct spoolss_AddDriverInfo3 info3;
1709 const char *arch;
1710 char *driver_args;
1711 struct dcerpc_binding_handle *b = cli->binding_handle;
1713 /* parse the command arguments */
1714 if (argc != 3 && argc != 4)
1716 printf ("Usage: %s <Environment> \\\n", argv[0]);
1717 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1718 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1719 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1720 printf ("\t[version]\n");
1722 return WERR_OK;
1725 /* Fill in the spoolss_AddDriverInfo3 struct */
1726 ZERO_STRUCT(info3);
1728 arch = cmd_spoolss_get_short_archi(argv[1]);
1729 if (!arch) {
1730 printf ("Error Unknown architecture [%s]\n", argv[1]);
1731 return WERR_INVALID_PARAM;
1734 set_drv_info_3_env(mem_ctx, &info3, arch);
1736 driver_args = talloc_strdup( mem_ctx, argv[2] );
1737 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1739 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1740 return WERR_INVALID_PARAM;
1743 /* if printer driver version specified, override the default version
1744 * used by the architecture. This allows installation of Windows
1745 * 2000 (version 3) printer drivers. */
1746 if (argc == 4)
1748 info3.version = atoi(argv[3]);
1752 info_ctr.level = level;
1753 info_ctr.info.info3 = &info3;
1755 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1756 cli->srv_name_slash,
1757 &info_ctr,
1758 &result);
1759 if (!NT_STATUS_IS_OK(status)) {
1760 return ntstatus_to_werror(status);
1762 if (W_ERROR_IS_OK(result)) {
1763 printf ("Printer Driver %s successfully installed.\n",
1764 info3.driver_name);
1767 return result;
1771 /****************************************************************************
1772 ****************************************************************************/
1774 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1775 TALLOC_CTX *mem_ctx,
1776 int argc, const char **argv)
1778 WERROR result;
1779 struct spoolss_SetPrinterInfoCtr info_ctr;
1780 struct spoolss_SetPrinterInfo2 info2;
1782 /* parse the command arguments */
1783 if (argc != 5)
1785 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1786 return WERR_OK;
1789 /* Fill in the DRIVER_INFO_2 struct */
1790 ZERO_STRUCT(info2);
1792 info2.printername = argv[1];
1793 info2.drivername = argv[3];
1794 info2.sharename = argv[2];
1795 info2.portname = argv[4];
1796 info2.comment = "Created by rpcclient";
1797 info2.printprocessor = "winprint";
1798 info2.datatype = "RAW";
1799 info2.devmode_ptr = 0;
1800 info2.secdesc_ptr = 0;
1801 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1802 info2.priority = 0;
1803 info2.defaultpriority = 0;
1804 info2.starttime = 0;
1805 info2.untiltime = 0;
1807 /* These three fields must not be used by AddPrinter()
1808 as defined in the MS Platform SDK documentation..
1809 --jerry
1810 info2.status = 0;
1811 info2.cjobs = 0;
1812 info2.averageppm = 0;
1815 info_ctr.level = 2;
1816 info_ctr.info.info2 = &info2;
1818 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1819 &info_ctr);
1820 if (W_ERROR_IS_OK(result))
1821 printf ("Printer %s successfully installed.\n", argv[1]);
1823 return result;
1826 /****************************************************************************
1827 ****************************************************************************/
1829 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1830 TALLOC_CTX *mem_ctx,
1831 int argc, const char **argv)
1833 struct policy_handle pol;
1834 WERROR result;
1835 NTSTATUS status;
1836 uint32_t level = 2;
1837 const char *printername;
1838 union spoolss_PrinterInfo info;
1839 struct spoolss_SetPrinterInfoCtr info_ctr;
1840 struct spoolss_SetPrinterInfo2 info2;
1841 struct spoolss_DevmodeContainer devmode_ctr;
1842 struct sec_desc_buf secdesc_ctr;
1843 struct dcerpc_binding_handle *b = cli->binding_handle;
1845 ZERO_STRUCT(devmode_ctr);
1846 ZERO_STRUCT(secdesc_ctr);
1848 /* parse the command arguments */
1849 if (argc != 3)
1851 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1852 return WERR_OK;
1855 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1857 /* Get a printer handle */
1859 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1860 printername,
1861 PRINTER_ALL_ACCESS,
1862 &pol);
1863 if (!W_ERROR_IS_OK(result))
1864 goto done;
1866 /* Get printer info */
1868 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1869 &pol,
1870 level,
1872 &info);
1873 if (!W_ERROR_IS_OK(result)) {
1874 printf ("Unable to retrieve printer information!\n");
1875 goto done;
1878 /* Set the printer driver */
1880 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1881 info2.drivername = argv[2];
1883 info_ctr.level = 2;
1884 info_ctr.info.info2 = &info2;
1886 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1887 &pol,
1888 &info_ctr,
1889 &devmode_ctr,
1890 &secdesc_ctr,
1891 0, /* command */
1892 &result);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 result = ntstatus_to_werror(status);
1895 goto done;
1897 if (!W_ERROR_IS_OK(result)) {
1898 printf("SetPrinter call failed!\n");
1899 goto done;
1902 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1904 done:
1905 /* Cleanup */
1907 if (is_valid_policy_hnd(&pol)) {
1908 WERROR _result;
1909 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1912 return result;
1916 /****************************************************************************
1917 ****************************************************************************/
1919 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1920 TALLOC_CTX *mem_ctx,
1921 int argc, const char **argv)
1923 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1924 NTSTATUS status;
1925 struct dcerpc_binding_handle *b = cli->binding_handle;
1927 int i;
1928 int vers = -1;
1930 const char *arch = NULL;
1931 uint32_t delete_flags = 0;
1933 /* parse the command arguments */
1934 if (argc < 2 || argc > 5) {
1935 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
1936 return WERR_OK;
1939 if (argc >= 3)
1940 arch = argv[2];
1941 if (argc >= 4) {
1942 vers = atoi(argv[3]);
1943 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1945 if (argc == 5)
1946 delete_flags = atoi(argv[4]);
1948 /* delete the driver for all architectures */
1949 for (i=0; archi_table[i].long_archi; i++) {
1951 if (arch && !strequal(archi_table[i].long_archi, arch))
1952 continue;
1954 if (vers >= 0 && archi_table[i].version != vers)
1955 continue;
1957 /* make the call to remove the driver */
1958 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1959 cli->srv_name_slash,
1960 archi_table[i].long_archi,
1961 argv[1],
1962 delete_flags,
1963 archi_table[i].version,
1964 &result);
1965 if (!NT_STATUS_IS_OK(status)) {
1966 return ntstatus_to_werror(status);
1968 if ( !W_ERROR_IS_OK(result) )
1970 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1971 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1972 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1975 else
1977 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1978 archi_table[i].long_archi, archi_table[i].version);
1979 ret = WERR_OK;
1983 return ret;
1987 /****************************************************************************
1988 ****************************************************************************/
1990 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1991 TALLOC_CTX *mem_ctx,
1992 int argc, const char **argv)
1994 WERROR result = WERR_OK;
1995 NTSTATUS status;
1996 int i;
1997 struct dcerpc_binding_handle *b = cli->binding_handle;
1999 /* parse the command arguments */
2000 if (argc != 2) {
2001 printf ("Usage: %s <driver>\n", argv[0]);
2002 return WERR_OK;
2005 /* delete the driver for all architectures */
2006 for (i=0; archi_table[i].long_archi; i++) {
2007 result = WERR_OK;
2009 /* make the call to remove the driver */
2010 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2011 cli->srv_name_slash,
2012 archi_table[i].long_archi,
2013 argv[1],
2014 &result);
2015 if (!NT_STATUS_IS_OK(status)) {
2016 result = ntstatus_to_werror(status);
2017 continue;
2019 if ( !W_ERROR_IS_OK(result) ) {
2020 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2021 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2022 argv[1], archi_table[i].long_archi,
2023 win_errstr(result));
2025 } else {
2026 printf ("Driver %s removed for arch [%s].\n", argv[1],
2027 archi_table[i].long_archi);
2031 return result;
2034 /****************************************************************************
2035 ****************************************************************************/
2037 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2038 TALLOC_CTX *mem_ctx,
2039 int argc, const char **argv)
2041 WERROR result;
2042 NTSTATUS status;
2043 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2044 DATA_BLOB buffer;
2045 uint32_t offered;
2046 union spoolss_PrintProcessorDirectoryInfo info;
2047 uint32_t needed;
2048 struct dcerpc_binding_handle *b = cli->binding_handle;
2050 /* parse the command arguments */
2051 if (argc > 2) {
2052 printf ("Usage: %s [environment]\n", argv[0]);
2053 return WERR_OK;
2056 if (argc == 2) {
2057 environment = argv[1];
2060 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2061 cli->srv_name_slash,
2062 environment,
2064 NULL, /* buffer */
2065 0, /* offered */
2066 NULL, /* info */
2067 &needed,
2068 &result);
2069 if (!NT_STATUS_IS_OK(status)) {
2070 return ntstatus_to_werror(status);
2072 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2073 offered = needed;
2074 buffer = data_blob_talloc_zero(mem_ctx, needed);
2076 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2077 cli->srv_name_slash,
2078 environment,
2080 &buffer,
2081 offered,
2082 &info,
2083 &needed,
2084 &result);
2085 if (!NT_STATUS_IS_OK(status)) {
2086 return ntstatus_to_werror(status);
2090 if (W_ERROR_IS_OK(result)) {
2091 printf("%s\n", info.info1.directory_name);
2094 return result;
2097 /****************************************************************************
2098 ****************************************************************************/
2100 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2101 int argc, const char **argv)
2103 struct policy_handle handle;
2104 WERROR werror;
2105 NTSTATUS status;
2106 const char *printername;
2107 union spoolss_AddFormInfo info;
2108 struct spoolss_AddFormInfo1 info1;
2109 struct spoolss_AddFormInfo2 info2;
2110 uint32_t level = 1;
2111 struct dcerpc_binding_handle *b = cli->binding_handle;
2113 /* Parse the command arguments */
2115 if (argc < 3 || argc > 5) {
2116 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2117 return WERR_OK;
2120 /* Get a printer handle */
2122 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2124 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2125 printername,
2126 PRINTER_ALL_ACCESS,
2127 &handle);
2128 if (!W_ERROR_IS_OK(werror))
2129 goto done;
2131 /* Dummy up some values for the form data */
2133 if (argc == 4) {
2134 level = atoi(argv[3]);
2137 switch (level) {
2138 case 1:
2139 info1.flags = SPOOLSS_FORM_USER;
2140 info1.form_name = argv[2];
2141 info1.size.width = 100;
2142 info1.size.height = 100;
2143 info1.area.left = 0;
2144 info1.area.top = 10;
2145 info1.area.right = 20;
2146 info1.area.bottom = 30;
2148 info.info1 = &info1;
2150 break;
2151 case 2:
2152 info2.flags = SPOOLSS_FORM_USER;
2153 info2.form_name = argv[2];
2154 info2.size.width = 100;
2155 info2.size.height = 100;
2156 info2.area.left = 0;
2157 info2.area.top = 10;
2158 info2.area.right = 20;
2159 info2.area.bottom = 30;
2160 info2.keyword = argv[2];
2161 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2162 info2.mui_dll = NULL;
2163 info2.ressource_id = 0;
2164 info2.display_name = argv[2];
2165 info2.lang_id = 0;
2167 info.info2 = &info2;
2169 break;
2170 default:
2171 werror = WERR_INVALID_PARAM;
2172 goto done;
2175 /* Add the form */
2178 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2179 &handle,
2180 level,
2181 info,
2182 &werror);
2183 if (!NT_STATUS_IS_OK(status)) {
2184 werror = ntstatus_to_werror(status);
2185 goto done;
2187 done:
2188 if (is_valid_policy_hnd(&handle)) {
2189 WERROR _result;
2190 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2193 return werror;
2196 /****************************************************************************
2197 ****************************************************************************/
2199 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2200 int argc, const char **argv)
2202 struct policy_handle handle;
2203 WERROR werror;
2204 NTSTATUS status;
2205 const char *printername;
2206 union spoolss_AddFormInfo info;
2207 struct spoolss_AddFormInfo1 info1;
2208 struct dcerpc_binding_handle *b = cli->binding_handle;
2210 /* Parse the command arguments */
2212 if (argc != 3) {
2213 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2214 return WERR_OK;
2217 /* Get a printer handle */
2219 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2221 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2222 printername,
2223 SEC_FLAG_MAXIMUM_ALLOWED,
2224 &handle);
2225 if (!W_ERROR_IS_OK(werror))
2226 goto done;
2228 /* Dummy up some values for the form data */
2230 info1.flags = SPOOLSS_FORM_PRINTER;
2231 info1.size.width = 100;
2232 info1.size.height = 100;
2233 info1.area.left = 0;
2234 info1.area.top = 1000;
2235 info1.area.right = 2000;
2236 info1.area.bottom = 3000;
2237 info1.form_name = argv[2];
2239 info.info1 = &info1;
2241 /* Set the form */
2243 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2244 &handle,
2245 argv[2],
2247 info,
2248 &werror);
2249 if (!NT_STATUS_IS_OK(status)) {
2250 werror = ntstatus_to_werror(status);
2251 goto done;
2253 done:
2254 if (is_valid_policy_hnd(&handle)) {
2255 WERROR _result;
2256 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2259 return werror;
2262 /****************************************************************************
2263 ****************************************************************************/
2265 static const char *get_form_flag(int form_flag)
2267 switch (form_flag) {
2268 case SPOOLSS_FORM_USER:
2269 return "FORM_USER";
2270 case SPOOLSS_FORM_BUILTIN:
2271 return "FORM_BUILTIN";
2272 case SPOOLSS_FORM_PRINTER:
2273 return "FORM_PRINTER";
2274 default:
2275 return "unknown";
2279 /****************************************************************************
2280 ****************************************************************************/
2282 static void display_form_info1(struct spoolss_FormInfo1 *r)
2284 printf("%s\n" \
2285 "\tflag: %s (%d)\n" \
2286 "\twidth: %d, length: %d\n" \
2287 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2288 r->form_name, get_form_flag(r->flags), r->flags,
2289 r->size.width, r->size.height,
2290 r->area.left, r->area.right,
2291 r->area.top, r->area.bottom);
2294 /****************************************************************************
2295 ****************************************************************************/
2297 static void display_form_info2(struct spoolss_FormInfo2 *r)
2299 printf("%s\n" \
2300 "\tflag: %s (%d)\n" \
2301 "\twidth: %d, length: %d\n" \
2302 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2303 r->form_name, get_form_flag(r->flags), r->flags,
2304 r->size.width, r->size.height,
2305 r->area.left, r->area.right,
2306 r->area.top, r->area.bottom);
2307 printf("\tkeyword: %s\n", r->keyword);
2308 printf("\tstring_type: 0x%08x\n", r->string_type);
2309 printf("\tmui_dll: %s\n", r->mui_dll);
2310 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2311 printf("\tdisplay_name: %s\n", r->display_name);
2312 printf("\tlang_id: %d\n", r->lang_id);
2313 printf("\n");
2316 /****************************************************************************
2317 ****************************************************************************/
2319 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2320 int argc, const char **argv)
2322 struct policy_handle handle;
2323 WERROR werror;
2324 NTSTATUS status;
2325 const char *printername;
2326 DATA_BLOB buffer;
2327 uint32_t offered = 0;
2328 union spoolss_FormInfo info;
2329 uint32_t needed;
2330 uint32_t level = 1;
2331 struct dcerpc_binding_handle *b = cli->binding_handle;
2333 /* Parse the command arguments */
2335 if (argc < 3 || argc > 5) {
2336 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2337 return WERR_OK;
2340 /* Get a printer handle */
2342 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2344 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2345 printername,
2346 SEC_FLAG_MAXIMUM_ALLOWED,
2347 &handle);
2348 if (!W_ERROR_IS_OK(werror))
2349 goto done;
2351 if (argc == 4) {
2352 level = atoi(argv[3]);
2355 /* Get the form */
2357 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2358 &handle,
2359 argv[2],
2360 level,
2361 NULL,
2362 offered,
2363 &info,
2364 &needed,
2365 &werror);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 werror = ntstatus_to_werror(status);
2368 goto done;
2370 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2371 buffer = data_blob_talloc_zero(mem_ctx, needed);
2372 offered = needed;
2373 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2374 &handle,
2375 argv[2],
2376 level,
2377 &buffer,
2378 offered,
2379 &info,
2380 &needed,
2381 &werror);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 werror = ntstatus_to_werror(status);
2384 goto done;
2388 if (!W_ERROR_IS_OK(werror)) {
2389 goto done;
2392 switch (level) {
2393 case 1:
2394 display_form_info1(&info.info1);
2395 break;
2396 case 2:
2397 display_form_info2(&info.info2);
2398 break;
2401 done:
2402 if (is_valid_policy_hnd(&handle)) {
2403 WERROR _result;
2404 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2407 return werror;
2410 /****************************************************************************
2411 ****************************************************************************/
2413 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2414 TALLOC_CTX *mem_ctx, int argc,
2415 const char **argv)
2417 struct policy_handle handle;
2418 WERROR werror;
2419 NTSTATUS status;
2420 const char *printername;
2421 struct dcerpc_binding_handle *b = cli->binding_handle;
2423 /* Parse the command arguments */
2425 if (argc != 3) {
2426 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2427 return WERR_OK;
2430 /* Get a printer handle */
2432 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2434 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2435 printername,
2436 SEC_FLAG_MAXIMUM_ALLOWED,
2437 &handle);
2438 if (!W_ERROR_IS_OK(werror))
2439 goto done;
2441 /* Delete the form */
2443 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2444 &handle,
2445 argv[2],
2446 &werror);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 werror = ntstatus_to_werror(status);
2449 goto done;
2452 done:
2453 if (is_valid_policy_hnd(&handle)) {
2454 WERROR _result;
2455 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2458 return werror;
2461 /****************************************************************************
2462 ****************************************************************************/
2464 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2465 TALLOC_CTX *mem_ctx, int argc,
2466 const char **argv)
2468 struct policy_handle handle;
2469 WERROR werror;
2470 const char *printername;
2471 uint32_t num_forms, level = 1, i;
2472 union spoolss_FormInfo *forms;
2473 struct dcerpc_binding_handle *b = cli->binding_handle;
2475 /* Parse the command arguments */
2477 if (argc < 2 || argc > 4) {
2478 printf ("Usage: %s <printer> [level]\n", argv[0]);
2479 return WERR_OK;
2482 /* Get a printer handle */
2484 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2486 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2487 printername,
2488 SEC_FLAG_MAXIMUM_ALLOWED,
2489 &handle);
2490 if (!W_ERROR_IS_OK(werror))
2491 goto done;
2493 if (argc == 3) {
2494 level = atoi(argv[2]);
2497 /* Enumerate forms */
2499 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2500 &handle,
2501 level,
2503 &num_forms,
2504 &forms);
2506 if (!W_ERROR_IS_OK(werror))
2507 goto done;
2509 /* Display output */
2511 for (i = 0; i < num_forms; i++) {
2512 switch (level) {
2513 case 1:
2514 display_form_info1(&forms[i].info1);
2515 break;
2516 case 2:
2517 display_form_info2(&forms[i].info2);
2518 break;
2522 done:
2523 if (is_valid_policy_hnd(&handle)) {
2524 WERROR _result;
2525 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2528 return werror;
2531 /****************************************************************************
2532 ****************************************************************************/
2534 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2535 TALLOC_CTX *mem_ctx,
2536 int argc, const char **argv)
2538 WERROR result;
2539 NTSTATUS status;
2540 const char *printername;
2541 struct policy_handle pol = { 0, };
2542 union spoolss_PrinterInfo info;
2543 enum winreg_Type type;
2544 union spoolss_PrinterData data;
2545 DATA_BLOB blob;
2546 struct dcerpc_binding_handle *b = cli->binding_handle;
2548 /* parse the command arguments */
2549 if (argc < 5) {
2550 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2551 " <value> <data>\n",
2552 argv[0]);
2553 return WERR_OK;
2556 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2558 type = REG_NONE;
2560 if (strequal(argv[2], "string")) {
2561 type = REG_SZ;
2564 if (strequal(argv[2], "binary")) {
2565 type = REG_BINARY;
2568 if (strequal(argv[2], "dword")) {
2569 type = REG_DWORD;
2572 if (strequal(argv[2], "multistring")) {
2573 type = REG_MULTI_SZ;
2576 if (type == REG_NONE) {
2577 printf("Unknown data type: %s\n", argv[2]);
2578 result = WERR_INVALID_PARAM;
2579 goto done;
2582 /* get a printer handle */
2584 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2585 printername,
2586 SEC_FLAG_MAXIMUM_ALLOWED,
2587 &pol);
2588 if (!W_ERROR_IS_OK(result)) {
2589 goto done;
2592 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2593 &pol,
2596 &info);
2597 if (!W_ERROR_IS_OK(result)) {
2598 goto done;
2601 printf("%s\n", current_timestring(mem_ctx, true));
2602 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2604 /* Set the printer data */
2606 switch (type) {
2607 case REG_SZ:
2608 data.string = talloc_strdup(mem_ctx, argv[4]);
2609 W_ERROR_HAVE_NO_MEMORY(data.string);
2610 break;
2611 case REG_DWORD:
2612 data.value = strtoul(argv[4], NULL, 10);
2613 break;
2614 case REG_BINARY:
2615 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2616 break;
2617 case REG_MULTI_SZ: {
2618 int i, num_strings;
2619 const char **strings = NULL;
2621 num_strings = 0;
2623 for (i=4; i<argc; i++) {
2624 if (strcmp(argv[i], "NULL") == 0) {
2625 argv[i] = "";
2627 if (!add_string_to_array(mem_ctx, argv[i],
2628 &strings,
2629 &num_strings)) {
2630 result = WERR_NOMEM;
2631 goto done;
2634 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2635 if (!data.string_array) {
2636 result = WERR_NOMEM;
2637 goto done;
2639 for (i=0; i < num_strings; i++) {
2640 data.string_array[i] = strings[i];
2642 break;
2644 default:
2645 printf("Unknown data type: %s\n", argv[2]);
2646 result = WERR_INVALID_PARAM;
2647 goto done;
2650 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2651 if (!W_ERROR_IS_OK(result)) {
2652 goto done;
2655 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2656 &pol,
2657 argv[3], /* value_name */
2658 type,
2659 blob.data,
2660 blob.length,
2661 &result);
2662 if (!NT_STATUS_IS_OK(status)) {
2663 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2664 result = ntstatus_to_werror(status);
2665 goto done;
2667 if (!W_ERROR_IS_OK(result)) {
2668 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2669 goto done;
2671 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2673 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2674 &pol,
2677 &info);
2678 if (!W_ERROR_IS_OK(result)) {
2679 goto done;
2682 printf("%s\n", current_timestring(mem_ctx, true));
2683 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2685 done:
2686 /* cleanup */
2687 if (is_valid_policy_hnd(&pol)) {
2688 WERROR _result;
2689 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2692 return result;
2695 /****************************************************************************
2696 ****************************************************************************/
2698 static void display_job_info1(struct spoolss_JobInfo1 *r)
2700 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2701 r->user_name, r->document_name, r->text_status, r->pages_printed,
2702 r->total_pages);
2705 /****************************************************************************
2706 ****************************************************************************/
2708 static void display_job_info2(struct spoolss_JobInfo2 *r)
2710 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2711 r->position, r->job_id,
2712 r->user_name, r->document_name, r->text_status, r->pages_printed,
2713 r->total_pages, r->size);
2716 /****************************************************************************
2717 ****************************************************************************/
2719 static void display_job_info3(struct spoolss_JobInfo3 *r)
2721 printf("jobid[%d], next_jobid[%d]\n",
2722 r->job_id, r->next_job_id);
2725 /****************************************************************************
2726 ****************************************************************************/
2728 static void display_job_info4(struct spoolss_JobInfo4 *r)
2730 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2731 r->position, r->job_id,
2732 r->user_name, r->document_name, r->text_status, r->pages_printed,
2733 r->total_pages, r->size, r->size_high);
2736 /****************************************************************************
2737 ****************************************************************************/
2739 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2740 TALLOC_CTX *mem_ctx, int argc,
2741 const char **argv)
2743 WERROR result;
2744 uint32_t level = 1, count, i;
2745 const char *printername;
2746 struct policy_handle hnd;
2747 union spoolss_JobInfo *info;
2748 struct dcerpc_binding_handle *b = cli->binding_handle;
2750 if (argc < 2 || argc > 3) {
2751 printf("Usage: %s printername [level]\n", argv[0]);
2752 return WERR_OK;
2755 if (argc == 3) {
2756 level = atoi(argv[2]);
2759 /* Open printer handle */
2761 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2763 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2764 printername,
2765 SEC_FLAG_MAXIMUM_ALLOWED,
2766 &hnd);
2767 if (!W_ERROR_IS_OK(result))
2768 goto done;
2770 /* Enumerate ports */
2772 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2773 &hnd,
2774 0, /* firstjob */
2775 1000, /* numjobs */
2776 level,
2778 &count,
2779 &info);
2780 if (!W_ERROR_IS_OK(result)) {
2781 goto done;
2784 for (i = 0; i < count; i++) {
2785 switch (level) {
2786 case 1:
2787 display_job_info1(&info[i].info1);
2788 break;
2789 case 2:
2790 display_job_info2(&info[i].info2);
2791 break;
2792 default:
2793 d_printf("unknown info level %d\n", level);
2794 break;
2798 done:
2799 if (is_valid_policy_hnd(&hnd)) {
2800 WERROR _result;
2801 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2804 return result;
2807 /****************************************************************************
2808 ****************************************************************************/
2810 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2811 TALLOC_CTX *mem_ctx, int argc,
2812 const char **argv)
2814 WERROR result;
2815 const char *printername;
2816 struct policy_handle hnd;
2817 uint32_t job_id;
2818 uint32_t level = 1;
2819 union spoolss_JobInfo info;
2820 struct dcerpc_binding_handle *b = cli->binding_handle;
2822 if (argc < 3 || argc > 4) {
2823 printf("Usage: %s printername job_id [level]\n", argv[0]);
2824 return WERR_OK;
2827 job_id = atoi(argv[2]);
2829 if (argc == 4) {
2830 level = atoi(argv[3]);
2833 /* Open printer handle */
2835 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2837 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2838 printername,
2839 SEC_FLAG_MAXIMUM_ALLOWED,
2840 &hnd);
2841 if (!W_ERROR_IS_OK(result)) {
2842 goto done;
2845 /* Enumerate ports */
2847 result = rpccli_spoolss_getjob(cli, mem_ctx,
2848 &hnd,
2849 job_id,
2850 level,
2852 &info);
2854 if (!W_ERROR_IS_OK(result)) {
2855 goto done;
2858 switch (level) {
2859 case 1:
2860 display_job_info1(&info.info1);
2861 break;
2862 case 2:
2863 display_job_info2(&info.info2);
2864 break;
2865 case 3:
2866 display_job_info3(&info.info3);
2867 break;
2868 case 4:
2869 display_job_info4(&info.info4);
2870 break;
2871 default:
2872 d_printf("unknown info level %d\n", level);
2873 break;
2876 done:
2877 if (is_valid_policy_hnd(&hnd)) {
2878 WERROR _result;
2879 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2882 return result;
2885 /****************************************************************************
2886 ****************************************************************************/
2888 static struct {
2889 const char *name;
2890 enum spoolss_JobControl val;
2891 } cmdvals[] = {
2892 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2893 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2894 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2895 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2896 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2897 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2898 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2899 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2900 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2903 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2905 int i;
2907 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2908 if (strequal(cmdvals[i].name, cmd)) {
2909 return cmdvals[i].val;
2912 return (enum spoolss_JobControl)atoi(cmd);
2915 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2916 TALLOC_CTX *mem_ctx, int argc,
2917 const char **argv)
2919 WERROR result;
2920 NTSTATUS status;
2921 const char *printername;
2922 struct policy_handle hnd;
2923 uint32_t job_id;
2924 enum spoolss_JobControl command;
2925 struct dcerpc_binding_handle *b = cli->binding_handle;
2927 if (argc != 4) {
2928 printf("Usage: %s printername job_id command\n", argv[0]);
2929 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2930 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2931 return WERR_OK;
2934 job_id = atoi(argv[2]);
2935 command = parse_setjob_command(argv[3]);
2937 /* Open printer handle */
2939 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2941 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2942 printername,
2943 SEC_FLAG_MAXIMUM_ALLOWED,
2944 &hnd);
2945 if (!W_ERROR_IS_OK(result)) {
2946 goto done;
2949 /* Set Job */
2951 status = dcerpc_spoolss_SetJob(b, mem_ctx,
2952 &hnd,
2953 job_id,
2954 NULL,
2955 command,
2956 &result);
2957 if (!NT_STATUS_IS_OK(status)) {
2958 result = ntstatus_to_werror(status);
2959 goto done;
2961 if (!W_ERROR_IS_OK(result)) {
2962 goto done;
2965 done:
2966 if (is_valid_policy_hnd(&hnd)) {
2967 WERROR _result;
2968 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2971 return result;
2974 /****************************************************************************
2975 ****************************************************************************/
2977 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2978 TALLOC_CTX *mem_ctx, int argc,
2979 const char **argv)
2981 WERROR result;
2982 NTSTATUS status;
2983 const char *printername;
2984 struct policy_handle hnd;
2985 uint32_t value_needed;
2986 enum winreg_Type type;
2987 uint32_t data_needed;
2988 struct dcerpc_binding_handle *b = cli->binding_handle;
2989 struct spoolss_EnumPrinterData r;
2991 if (argc != 2) {
2992 printf("Usage: %s printername\n", argv[0]);
2993 return WERR_OK;
2996 /* Open printer handle */
2998 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3000 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3001 printername,
3002 SEC_FLAG_MAXIMUM_ALLOWED,
3003 &hnd);
3004 if (!W_ERROR_IS_OK(result)) {
3005 goto done;
3008 /* Enumerate data */
3010 r.in.handle = &hnd;
3011 r.in.enum_index = 0;
3012 r.in.value_offered = 0;
3013 r.in.data_offered = 0;
3014 r.out.value_name = NULL;
3015 r.out.value_needed = &value_needed;
3016 r.out.type = &type;
3017 r.out.data = NULL;
3018 r.out.data_needed = &data_needed;
3020 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3021 if (!NT_STATUS_IS_OK(status)) {
3022 result = ntstatus_to_werror(status);
3023 goto done;
3026 if (!W_ERROR_IS_OK(r.out.result)) {
3027 result = r.out.result;
3028 goto done;
3031 r.in.data_offered = *r.out.data_needed;
3032 r.in.value_offered = *r.out.value_needed;
3033 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3034 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3036 do {
3038 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3039 if (!NT_STATUS_IS_OK(status)) {
3040 result = ntstatus_to_werror(status);
3041 goto done;
3044 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3045 result = WERR_OK;
3046 break;
3049 r.in.enum_index++;
3051 display_reg_value(r.out.value_name, *r.out.type,
3052 data_blob_const(r.out.data, r.in.data_offered));
3054 } while (W_ERROR_IS_OK(r.out.result));
3056 done:
3057 if (is_valid_policy_hnd(&hnd)) {
3058 WERROR _result;
3059 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3062 return result;
3065 /****************************************************************************
3066 ****************************************************************************/
3068 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3069 TALLOC_CTX *mem_ctx, int argc,
3070 const char **argv)
3072 WERROR result;
3073 uint32_t i;
3074 const char *printername;
3075 struct policy_handle hnd;
3076 uint32_t count;
3077 struct spoolss_PrinterEnumValues *info;
3078 struct dcerpc_binding_handle *b = cli->binding_handle;
3080 if (argc != 3) {
3081 printf("Usage: %s printername <keyname>\n", argv[0]);
3082 return WERR_OK;
3085 /* Open printer handle */
3087 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3089 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3090 printername,
3091 SEC_FLAG_MAXIMUM_ALLOWED,
3092 &hnd);
3093 if (!W_ERROR_IS_OK(result)) {
3094 goto done;
3097 /* Enumerate subkeys */
3099 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3100 &hnd,
3101 argv[2],
3103 &count,
3104 &info);
3105 if (!W_ERROR_IS_OK(result)) {
3106 goto done;
3109 for (i=0; i < count; i++) {
3110 display_printer_data(info[i].value_name,
3111 info[i].type,
3112 info[i].data->data,
3113 info[i].data->length);
3116 done:
3117 if (is_valid_policy_hnd(&hnd)) {
3118 WERROR _result;
3119 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3122 return result;
3125 /****************************************************************************
3126 ****************************************************************************/
3128 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3129 TALLOC_CTX *mem_ctx, int argc,
3130 const char **argv)
3132 WERROR result;
3133 const char *printername;
3134 const char *keyname = NULL;
3135 struct policy_handle hnd;
3136 const char **key_buffer = NULL;
3137 int i;
3138 uint32_t offered = 0;
3139 struct dcerpc_binding_handle *b = cli->binding_handle;
3141 if (argc < 2 || argc > 4) {
3142 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3143 return WERR_OK;
3146 if (argc >= 3) {
3147 keyname = argv[2];
3148 } else {
3149 keyname = "";
3152 if (argc == 4) {
3153 offered = atoi(argv[3]);
3156 /* Open printer handle */
3158 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3160 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3161 printername,
3162 SEC_FLAG_MAXIMUM_ALLOWED,
3163 &hnd);
3164 if (!W_ERROR_IS_OK(result)) {
3165 goto done;
3168 /* Enumerate subkeys */
3170 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3171 &hnd,
3172 keyname,
3173 &key_buffer,
3174 offered);
3176 if (!W_ERROR_IS_OK(result)) {
3177 goto done;
3180 for (i=0; key_buffer && key_buffer[i]; i++) {
3181 printf("%s\n", key_buffer[i]);
3184 done:
3186 if (is_valid_policy_hnd(&hnd)) {
3187 WERROR _result;
3188 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3191 return result;
3194 /****************************************************************************
3195 ****************************************************************************/
3197 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3198 TALLOC_CTX *mem_ctx, int argc,
3199 const char **argv)
3201 const char *printername;
3202 const char *clientname;
3203 struct policy_handle hnd = { 0, };
3204 WERROR result;
3205 NTSTATUS status;
3206 struct spoolss_NotifyOption option;
3207 struct dcerpc_binding_handle *b = cli->binding_handle;
3209 if (argc != 2) {
3210 printf("Usage: %s printername\n", argv[0]);
3211 result = WERR_OK;
3212 goto done;
3215 /* Open printer */
3217 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3219 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3220 printername,
3221 SEC_FLAG_MAXIMUM_ALLOWED,
3222 &hnd);
3223 if (!W_ERROR_IS_OK(result)) {
3224 printf("Error opening %s\n", argv[1]);
3225 goto done;
3228 /* Create spool options */
3230 option.version = 2;
3231 option.count = 2;
3233 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3234 if (option.types == NULL) {
3235 result = WERR_NOMEM;
3236 goto done;
3239 option.types[0].type = PRINTER_NOTIFY_TYPE;
3240 option.types[0].count = 1;
3241 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3242 if (option.types[0].fields == NULL) {
3243 result = WERR_NOMEM;
3244 goto done;
3246 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3248 option.types[1].type = JOB_NOTIFY_TYPE;
3249 option.types[1].count = 1;
3250 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3251 if (option.types[1].fields == NULL) {
3252 result = WERR_NOMEM;
3253 goto done;
3255 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3257 clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3258 if (!clientname) {
3259 result = WERR_NOMEM;
3260 goto done;
3263 /* Send rffpcnex */
3265 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3266 &hnd,
3269 clientname,
3270 123,
3271 &option,
3272 &result);
3273 if (!NT_STATUS_IS_OK(status)) {
3274 result = ntstatus_to_werror(status);
3275 goto done;
3277 if (!W_ERROR_IS_OK(result)) {
3278 printf("Error rffpcnex %s\n", argv[1]);
3279 goto done;
3282 done:
3283 if (is_valid_policy_hnd(&hnd)) {
3284 WERROR _result;
3285 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3288 return result;
3291 /****************************************************************************
3292 ****************************************************************************/
3294 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3295 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3297 union spoolss_PrinterInfo info1, info2;
3298 WERROR werror;
3299 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3301 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3302 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3303 hnd1,
3306 &info1);
3307 if ( !W_ERROR_IS_OK(werror) ) {
3308 printf("failed (%s)\n", win_errstr(werror));
3309 talloc_destroy(mem_ctx);
3310 return false;
3312 printf("ok\n");
3314 printf("Retrieving printer properties for %s...", cli2->desthost);
3315 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3316 hnd2,
3319 &info2);
3320 if ( !W_ERROR_IS_OK(werror) ) {
3321 printf("failed (%s)\n", win_errstr(werror));
3322 talloc_destroy(mem_ctx);
3323 return false;
3325 printf("ok\n");
3327 talloc_destroy(mem_ctx);
3329 return true;
3332 /****************************************************************************
3333 ****************************************************************************/
3335 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3336 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3338 union spoolss_PrinterInfo info1, info2;
3339 WERROR werror;
3340 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3341 struct security_descriptor *sd1, *sd2;
3342 bool result = true;
3345 printf("Retrieving printer security for %s...", cli1->desthost);
3346 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3347 hnd1,
3350 &info1);
3351 if ( !W_ERROR_IS_OK(werror) ) {
3352 printf("failed (%s)\n", win_errstr(werror));
3353 result = false;
3354 goto done;
3356 printf("ok\n");
3358 printf("Retrieving printer security for %s...", cli2->desthost);
3359 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3360 hnd2,
3363 &info2);
3364 if ( !W_ERROR_IS_OK(werror) ) {
3365 printf("failed (%s)\n", win_errstr(werror));
3366 result = false;
3367 goto done;
3369 printf("ok\n");
3372 printf("++ ");
3374 sd1 = info1.info3.secdesc;
3375 sd2 = info2.info3.secdesc;
3377 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3378 printf("NULL secdesc!\n");
3379 result = false;
3380 goto done;
3383 if (!security_descriptor_equal( sd1, sd2 ) ) {
3384 printf("Security Descriptors *not* equal!\n");
3385 result = false;
3386 goto done;
3389 printf("Security descriptors match\n");
3391 done:
3392 talloc_destroy(mem_ctx);
3393 return result;
3397 /****************************************************************************
3398 ****************************************************************************/
3400 extern struct user_auth_info *rpcclient_auth_info;
3402 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3403 TALLOC_CTX *mem_ctx, int argc,
3404 const char **argv)
3406 const char *printername;
3407 char *printername_path = NULL;
3408 struct cli_state *cli_server2 = NULL;
3409 struct rpc_pipe_client *cli2 = NULL;
3410 struct policy_handle hPrinter1, hPrinter2;
3411 NTSTATUS nt_status;
3412 WERROR werror;
3414 if ( argc != 3 ) {
3415 printf("Usage: %s <printer> <server>\n", argv[0]);
3416 return WERR_OK;
3419 printername = argv[1];
3421 /* first get the connection to the remote server */
3423 nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
3424 NULL, 0,
3425 "IPC$", "IPC",
3426 get_cmdline_auth_info_username(rpcclient_auth_info),
3427 lp_workgroup(),
3428 get_cmdline_auth_info_password(rpcclient_auth_info),
3429 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3430 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3432 if ( !NT_STATUS_IS_OK(nt_status) )
3433 return WERR_GENERAL_FAILURE;
3435 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3436 &cli2);
3437 if (!NT_STATUS_IS_OK(nt_status)) {
3438 printf("failed to open spoolss pipe on server %s (%s)\n",
3439 argv[2], nt_errstr(nt_status));
3440 return WERR_GENERAL_FAILURE;
3443 /* now open up both printers */
3445 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3447 printf("Opening %s...", printername_path);
3449 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3450 printername_path,
3451 PRINTER_ALL_ACCESS,
3452 &hPrinter1);
3453 if ( !W_ERROR_IS_OK(werror) ) {
3454 printf("failed (%s)\n", win_errstr(werror));
3455 goto done;
3457 printf("ok\n");
3459 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3461 printf("Opening %s...", printername_path);
3462 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3463 printername_path,
3464 PRINTER_ALL_ACCESS,
3465 &hPrinter2);
3466 if ( !W_ERROR_IS_OK(werror) ) {
3467 printf("failed (%s)\n", win_errstr(werror));
3468 goto done;
3470 printf("ok\n");
3472 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3473 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3474 #if 0
3475 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3476 #endif
3479 done:
3480 /* cleanup */
3482 printf("Closing printers...");
3484 WERROR _result;
3485 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3486 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3488 printf("ok\n");
3490 /* close the second remote connection */
3492 cli_shutdown( cli_server2 );
3493 return WERR_OK;
3496 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3498 printf("print_processor_name: %s\n", r->print_processor_name);
3501 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3502 TALLOC_CTX *mem_ctx, int argc,
3503 const char **argv)
3505 WERROR werror;
3506 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3507 uint32_t num_procs, level = 1, i;
3508 union spoolss_PrintProcessorInfo *procs;
3510 /* Parse the command arguments */
3512 if (argc < 1 || argc > 4) {
3513 printf ("Usage: %s [environment] [level]\n", argv[0]);
3514 return WERR_OK;
3517 if (argc >= 2) {
3518 environment = argv[1];
3521 if (argc == 3) {
3522 level = atoi(argv[2]);
3525 /* Enumerate Print Processors */
3527 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3528 cli->srv_name_slash,
3529 environment,
3530 level,
3532 &num_procs,
3533 &procs);
3534 if (!W_ERROR_IS_OK(werror))
3535 goto done;
3537 /* Display output */
3539 for (i = 0; i < num_procs; i++) {
3540 switch (level) {
3541 case 1:
3542 display_proc_info1(&procs[i].info1);
3543 break;
3547 done:
3548 return werror;
3551 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3553 printf("name_array: %s\n", r->name_array);
3556 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3557 TALLOC_CTX *mem_ctx, int argc,
3558 const char **argv)
3560 WERROR werror;
3561 const char *print_processor_name = "winprint";
3562 uint32_t num_procs, level = 1, i;
3563 union spoolss_PrintProcDataTypesInfo *procs;
3565 /* Parse the command arguments */
3567 if (argc < 1 || argc > 4) {
3568 printf ("Usage: %s [environment] [level]\n", argv[0]);
3569 return WERR_OK;
3572 if (argc >= 2) {
3573 print_processor_name = argv[1];
3576 if (argc == 3) {
3577 level = atoi(argv[2]);
3580 /* Enumerate Print Processor Data Types */
3582 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3583 cli->srv_name_slash,
3584 print_processor_name,
3585 level,
3587 &num_procs,
3588 &procs);
3589 if (!W_ERROR_IS_OK(werror))
3590 goto done;
3592 /* Display output */
3594 for (i = 0; i < num_procs; i++) {
3595 switch (level) {
3596 case 1:
3597 display_proc_data_types_info1(&procs[i].info1);
3598 break;
3602 done:
3603 return werror;
3606 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3608 printf("monitor_name: %s\n", r->monitor_name);
3611 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3613 printf("monitor_name: %s\n", r->monitor_name);
3614 printf("environment: %s\n", r->environment);
3615 printf("dll_name: %s\n", r->dll_name);
3618 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3619 TALLOC_CTX *mem_ctx, int argc,
3620 const char **argv)
3622 WERROR werror;
3623 uint32_t count, level = 1, i;
3624 union spoolss_MonitorInfo *info;
3626 /* Parse the command arguments */
3628 if (argc > 2) {
3629 printf("Usage: %s [level]\n", argv[0]);
3630 return WERR_OK;
3633 if (argc == 2) {
3634 level = atoi(argv[1]);
3637 /* Enumerate Print Monitors */
3639 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3640 cli->srv_name_slash,
3641 level,
3643 &count,
3644 &info);
3645 if (!W_ERROR_IS_OK(werror)) {
3646 goto done;
3649 /* Display output */
3651 for (i = 0; i < count; i++) {
3652 switch (level) {
3653 case 1:
3654 display_monitor1(&info[i].info1);
3655 break;
3656 case 2:
3657 display_monitor2(&info[i].info2);
3658 break;
3662 done:
3663 return werror;
3666 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3667 TALLOC_CTX *mem_ctx, int argc,
3668 const char **argv)
3670 WERROR result;
3671 NTSTATUS status;
3672 struct policy_handle handle, gdi_handle;
3673 const char *printername;
3674 struct spoolss_DevmodeContainer devmode_ctr;
3675 struct dcerpc_binding_handle *b = cli->binding_handle;
3677 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3679 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3680 printername,
3681 SEC_FLAG_MAXIMUM_ALLOWED,
3682 &handle);
3683 if (!W_ERROR_IS_OK(result)) {
3684 return result;
3687 ZERO_STRUCT(devmode_ctr);
3689 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3690 &handle,
3691 &gdi_handle,
3692 &devmode_ctr,
3693 &result);
3694 if (!NT_STATUS_IS_OK(status)) {
3695 result = ntstatus_to_werror(status);
3696 goto done;
3698 if (!W_ERROR_IS_OK(result)) {
3699 goto done;
3702 done:
3703 if (is_valid_policy_hnd(&gdi_handle)) {
3704 WERROR _result;
3705 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3707 if (is_valid_policy_hnd(&handle)) {
3708 WERROR _result;
3709 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3712 return result;
3715 /* List of commands exported by this module */
3716 struct cmd_set spoolss_commands[] = {
3718 { "SPOOLSS" },
3720 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss, NULL, "Add a print driver", "" },
3721 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss, NULL, "Add a printer", "" },
3722 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss, NULL, "Delete a printer driver", "" },
3723 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss, NULL, "Delete a printer driver with files", "" },
3724 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss, NULL, "Enumerate printer data", "" },
3725 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss, NULL, "Enumerate printer data for a key", "" },
3726 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss, NULL, "Enumerate printer keys", "" },
3727 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss, NULL, "Enumerate print jobs", "" },
3728 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss, NULL, "Get print job", "" },
3729 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss, NULL, "Set print job", "" },
3730 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss, NULL, "Enumerate printer ports", "" },
3731 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss, NULL, "Enumerate installed printer drivers", "" },
3732 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss, NULL, "Enumerate printers", "" },
3733 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss, NULL, "Get print driver data", "" },
3734 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss, NULL, "Get printer driver data with keyname", ""},
3735 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss, NULL, "Get print driver information", "" },
3736 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss, NULL, "Get print driver upload directory", "" },
3737 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss, NULL, "Get printer info", "" },
3738 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss, NULL, "Open printer handle", "" },
3739 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss, NULL, "Open printer handle", "" },
3740 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss, NULL, "Set printer driver", "" },
3741 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss, NULL, "Get print processor directory", "" },
3742 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss, NULL, "Add form", "" },
3743 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss, NULL, "Set form", "" },
3744 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss, NULL, "Get form", "" },
3745 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss, NULL, "Delete form", "" },
3746 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss, NULL, "Enumerate forms", "" },
3747 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss, NULL, "Set printer comment", "" },
3748 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss, NULL, "Set printername", "" },
3749 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss, NULL, "Set REG_SZ printer data", "" },
3750 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss, NULL, "Rffpcnex test", "" },
3751 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss, NULL, "Printer comparison test", "" },
3752 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss, NULL, "Enumerate Print Processors", "" },
3753 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3754 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss, NULL, "Enumerate Print Monitors", "" },
3755 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss, NULL, "Create Printer IC", "" },
3757 { NULL }