Tiny simplification to dom_sid_string_buf
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blobda9826ae0e441b837dccf6b9f6fbbd36c873dd98
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 "registry/reg_objects.h"
31 #include "nt_printing.h"
32 #include "../libcli/security/display_sec.h"
33 #include "../libcli/security/security_descriptor.h"
34 #include "../libcli/registry/util_reg.h"
35 #include "libsmb/libsmb.h"
37 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
38 { \
39 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
40 _cli->srv_name_slash, _arg); \
41 W_ERROR_HAVE_NO_MEMORY(_printername); \
44 /* The version int is used by getdrivers. Note that
45 all architecture strings that support mutliple
46 versions must be grouped together since enumdrivers
47 uses this property to prevent issuing multiple
48 enumdriver calls for the same arch */
51 static const struct print_architecture_table_node archi_table[]= {
53 {"Windows 4.0", "WIN40", 0 },
54 {"Windows NT x86", "W32X86", 2 },
55 {"Windows NT x86", "W32X86", 3 },
56 {"Windows NT R4000", "W32MIPS", 2 },
57 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
58 {"Windows NT PowerPC", "W32PPC", 2 },
59 {"Windows IA64", "IA64", 3 },
60 {"Windows x64", "x64", 3 },
61 {NULL, "", -1 }
64 /**
65 * @file
67 * rpcclient module for SPOOLSS rpc pipe.
69 * This generally just parses and checks command lines, and then calls
70 * a cli_spoolss function.
71 **/
73 /****************************************************************************
74 function to do the mapping between the long architecture name and
75 the short one.
76 ****************************************************************************/
78 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
80 int i=-1;
82 DEBUG(107,("Getting architecture dependent directory\n"));
83 do {
84 i++;
85 } while ( (archi_table[i].long_archi!=NULL ) &&
86 strcasecmp_m(long_archi, archi_table[i].long_archi) );
88 if (archi_table[i].long_archi==NULL) {
89 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
90 return NULL;
93 /* this might be client code - but shouldn't this be an fstrcpy etc? */
96 DEBUGADD(108,("index: [%d]\n", i));
97 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
98 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
100 return archi_table[i].short_archi;
103 /****************************************************************************
104 ****************************************************************************/
106 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
107 TALLOC_CTX *mem_ctx,
108 int argc, const char **argv)
110 WERROR werror;
111 struct policy_handle hnd;
112 uint32_t access_mask = PRINTER_ALL_ACCESS;
113 struct dcerpc_binding_handle *b = cli->binding_handle;
115 if (argc < 2) {
116 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
117 return WERR_OK;
120 if (argc >= 3) {
121 sscanf(argv[2], "%x", &access_mask);
124 /* Open the printer handle */
126 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
127 argv[1],
128 access_mask,
129 &hnd);
130 if (W_ERROR_IS_OK(werror)) {
131 printf("Printer %s opened successfully\n", argv[1]);
132 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
134 if (!W_ERROR_IS_OK(werror)) {
135 printf("Error closing printer handle! (%s)\n",
136 get_dos_error_msg(werror));
140 return werror;
143 /****************************************************************************
144 ****************************************************************************/
146 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
147 TALLOC_CTX *mem_ctx,
148 int argc, const char **argv)
150 WERROR werror;
151 struct policy_handle hnd;
152 uint32_t access_mask = PRINTER_ALL_ACCESS;
153 NTSTATUS status;
154 struct spoolss_DevmodeContainer devmode_ctr;
155 struct dcerpc_binding_handle *b = cli->binding_handle;
157 ZERO_STRUCT(devmode_ctr);
159 if (argc < 2) {
160 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
161 return WERR_OK;
164 if (argc >= 3) {
165 sscanf(argv[2], "%x", &access_mask);
168 /* Open the printer handle */
170 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
171 argv[1],
172 NULL,
173 devmode_ctr,
174 access_mask,
175 &hnd,
176 &werror);
177 if (!NT_STATUS_IS_OK(status)) {
178 return ntstatus_to_werror(status);
180 if (W_ERROR_IS_OK(werror)) {
181 printf("Printer %s opened successfully\n", argv[1]);
182 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
184 if (!W_ERROR_IS_OK(werror)) {
185 printf("Error closing printer handle! (%s)\n",
186 get_dos_error_msg(werror));
190 return werror;
193 /****************************************************************************
194 ****************************************************************************/
196 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
198 if (!r)
199 return;
201 printf("\tprintername:[%s]\n", r->printername);
202 printf("\tservername:[%s]\n", r->servername);
203 printf("\tcjobs:[0x%x]\n", r->cjobs);
204 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
205 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
206 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
207 r->time.day, r->time.day_of_week);
208 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
209 r->time.second, r->time.millisecond);
211 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
212 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
214 printf("\tversion:[0x%x]\n", r->version);
215 printf("\tfree_build:[0x%x]\n", r->free_build);
216 printf("\tspooling:[0x%x]\n", r->spooling);
217 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
218 printf("\tsession_counter:[0x%x]\n", r->session_counter);
219 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
220 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
221 printf("\tjob_error:[0x%x]\n", r->job_error);
222 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
223 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
224 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
225 printf("\tchange_id:[0x%x]\n", r->change_id);
226 printf("\tlast_error: %s\n", win_errstr(r->last_error));
227 printf("\tstatus:[0x%x]\n", r->status);
228 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
229 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
230 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
231 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
232 printf("\tref_ic:[0x%x]\n", r->ref_ic);
233 printf("\treserved2:[0x%x]\n", r->reserved2);
234 printf("\treserved3:[0x%x]\n", r->reserved3);
236 printf("\n");
239 /****************************************************************************
240 ****************************************************************************/
242 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
244 printf("\tflags:[0x%x]\n", r->flags);
245 printf("\tname:[%s]\n", r->name);
246 printf("\tdescription:[%s]\n", r->description);
247 printf("\tcomment:[%s]\n", r->comment);
249 printf("\n");
252 /****************************************************************************
253 ****************************************************************************/
255 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
257 printf("\tservername:[%s]\n", r->servername);
258 printf("\tprintername:[%s]\n", r->printername);
259 printf("\tsharename:[%s]\n", r->sharename);
260 printf("\tportname:[%s]\n", r->portname);
261 printf("\tdrivername:[%s]\n", r->drivername);
262 printf("\tcomment:[%s]\n", r->comment);
263 printf("\tlocation:[%s]\n", r->location);
264 printf("\tsepfile:[%s]\n", r->sepfile);
265 printf("\tprintprocessor:[%s]\n", r->printprocessor);
266 printf("\tdatatype:[%s]\n", r->datatype);
267 printf("\tparameters:[%s]\n", r->parameters);
268 printf("\tattributes:[0x%x]\n", r->attributes);
269 printf("\tpriority:[0x%x]\n", r->priority);
270 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
271 printf("\tstarttime:[0x%x]\n", r->starttime);
272 printf("\tuntiltime:[0x%x]\n", r->untiltime);
273 printf("\tstatus:[0x%x]\n", r->status);
274 printf("\tcjobs:[0x%x]\n", r->cjobs);
275 printf("\taverageppm:[0x%x]\n", r->averageppm);
277 if (r->secdesc)
278 display_sec_desc(r->secdesc);
280 printf("\n");
283 /****************************************************************************
284 ****************************************************************************/
286 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
288 display_sec_desc(r->secdesc);
290 printf("\n");
293 /****************************************************************************
294 ****************************************************************************/
296 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
298 printf("\tservername:[%s]\n", r->servername);
299 printf("\tprintername:[%s]\n", r->printername);
300 printf("\tattributes:[0x%x]\n", r->attributes);
301 printf("\n");
304 /****************************************************************************
305 ****************************************************************************/
307 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
309 printf("\tprintername:[%s]\n", r->printername);
310 printf("\tportname:[%s]\n", r->portname);
311 printf("\tattributes:[0x%x]\n", r->attributes);
312 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
313 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
314 printf("\n");
317 /****************************************************************************
318 ****************************************************************************/
320 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
322 printf("\tstatus:[0x%x]\n", r->status);
323 printf("\n");
326 /****************************************************************************
327 ****************************************************************************/
329 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
331 printf("\tguid:[%s]\n", r->guid);
332 printf("\taction:[0x%x]\n", r->action);
333 printf("\n");
336 /****************************************************************************
337 ****************************************************************************/
339 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
340 TALLOC_CTX *mem_ctx,
341 int argc, const char **argv)
343 WERROR result;
344 uint32_t level = 1;
345 union spoolss_PrinterInfo *info;
346 uint32_t i, count;
347 const char *name;
348 uint32_t flags = PRINTER_ENUM_LOCAL;
350 if (argc > 4) {
351 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
352 return WERR_OK;
355 if (argc >= 2) {
356 level = atoi(argv[1]);
359 if (argc >= 3) {
360 name = argv[2];
361 } else {
362 name = cli->srv_name_slash;
365 if (argc == 4) {
366 flags = atoi(argv[3]);
369 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
370 flags,
371 name,
372 level,
374 &count,
375 &info);
376 if (W_ERROR_IS_OK(result)) {
378 if (!count) {
379 printf ("No printers returned.\n");
380 goto done;
383 for (i = 0; i < count; i++) {
384 switch (level) {
385 case 0:
386 display_print_info0(&info[i].info0);
387 break;
388 case 1:
389 display_print_info1(&info[i].info1);
390 break;
391 case 2:
392 display_print_info2(&info[i].info2);
393 break;
394 case 3:
395 display_print_info3(&info[i].info3);
396 break;
397 case 4:
398 display_print_info4(&info[i].info4);
399 break;
400 case 5:
401 display_print_info5(&info[i].info5);
402 break;
403 case 6:
404 display_print_info6(&info[i].info6);
405 break;
406 default:
407 printf("unknown info level %d\n", level);
408 goto done;
412 done:
414 return result;
417 /****************************************************************************
418 ****************************************************************************/
420 static void display_port_info_1(struct spoolss_PortInfo1 *r)
422 printf("\tPort Name:\t[%s]\n", r->port_name);
425 /****************************************************************************
426 ****************************************************************************/
428 static void display_port_info_2(struct spoolss_PortInfo2 *r)
430 printf("\tPort Name:\t[%s]\n", r->port_name);
431 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
432 printf("\tDescription:\t[%s]\n", r->description);
433 printf("\tPort Type:\t" );
434 if (r->port_type) {
435 int comma = 0; /* hack */
436 printf( "[" );
437 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
438 printf( "Read" );
439 comma = 1;
441 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
442 printf( "%sWrite", comma ? ", " : "" );
443 comma = 1;
445 /* These two have slightly different interpretations
446 on 95/98/ME but I'm disregarding that for now */
447 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
448 printf( "%sRedirected", comma ? ", " : "" );
449 comma = 1;
451 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
452 printf( "%sNet-Attached", comma ? ", " : "" );
454 printf( "]\n" );
455 } else {
456 printf( "[Unset]\n" );
458 printf("\tReserved:\t[%d]\n", r->reserved);
459 printf("\n");
462 /****************************************************************************
463 ****************************************************************************/
465 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
466 TALLOC_CTX *mem_ctx, int argc,
467 const char **argv)
469 WERROR result;
470 uint32_t level = 1;
471 uint32_t count;
472 union spoolss_PortInfo *info;
474 if (argc > 2) {
475 printf("Usage: %s [level]\n", argv[0]);
476 return WERR_OK;
479 if (argc == 2) {
480 level = atoi(argv[1]);
483 /* Enumerate ports */
485 result = rpccli_spoolss_enumports(cli, mem_ctx,
486 cli->srv_name_slash,
487 level,
489 &count,
490 &info);
491 if (W_ERROR_IS_OK(result)) {
492 int i;
494 for (i = 0; i < count; i++) {
495 switch (level) {
496 case 1:
497 display_port_info_1(&info[i].info1);
498 break;
499 case 2:
500 display_port_info_2(&info[i].info2);
501 break;
502 default:
503 printf("unknown info level %d\n", level);
504 break;
509 return result;
512 /****************************************************************************
513 ****************************************************************************/
515 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
516 TALLOC_CTX *mem_ctx,
517 int argc, const char **argv)
519 struct policy_handle pol;
520 WERROR result;
521 NTSTATUS status;
522 uint32_t info_level = 2;
523 union spoolss_PrinterInfo info;
524 struct spoolss_SetPrinterInfoCtr info_ctr;
525 struct spoolss_SetPrinterInfo2 info2;
526 const char *printername, *comment = NULL;
527 struct spoolss_DevmodeContainer devmode_ctr;
528 struct sec_desc_buf secdesc_ctr;
529 struct dcerpc_binding_handle *b = cli->binding_handle;
531 if (argc == 1 || argc > 3) {
532 printf("Usage: %s printername comment\n", argv[0]);
534 return WERR_OK;
537 /* Open a printer handle */
538 if (argc == 3) {
539 comment = argv[2];
542 ZERO_STRUCT(devmode_ctr);
543 ZERO_STRUCT(secdesc_ctr);
545 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
547 /* get a printer handle */
548 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
549 printername,
550 PRINTER_ALL_ACCESS,
551 &pol);
552 if (!W_ERROR_IS_OK(result))
553 goto done;
555 /* Get printer info */
556 result = rpccli_spoolss_getprinter(cli, mem_ctx,
557 &pol,
558 info_level,
560 &info);
561 if (!W_ERROR_IS_OK(result))
562 goto done;
565 /* Modify the comment. */
566 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
567 info2.comment = comment;
569 info_ctr.level = 2;
570 info_ctr.info.info2 = &info2;
572 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
573 &pol,
574 &info_ctr,
575 &devmode_ctr,
576 &secdesc_ctr,
577 0, /* command */
578 &result);
579 if (!NT_STATUS_IS_OK(status)) {
580 result = ntstatus_to_werror(status);
581 goto done;
583 if (W_ERROR_IS_OK(result))
584 printf("Success in setting comment.\n");
586 done:
587 if (is_valid_policy_hnd(&pol)) {
588 WERROR _result;
589 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
592 return result;
595 /****************************************************************************
596 ****************************************************************************/
598 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
599 TALLOC_CTX *mem_ctx,
600 int argc, const char **argv)
602 struct policy_handle pol;
603 WERROR result;
604 NTSTATUS status;
605 uint32_t info_level = 2;
606 union spoolss_PrinterInfo info;
607 const char *printername,
608 *new_printername = NULL;
609 struct spoolss_SetPrinterInfoCtr info_ctr;
610 struct spoolss_SetPrinterInfo2 info2;
611 struct spoolss_DevmodeContainer devmode_ctr;
612 struct sec_desc_buf secdesc_ctr;
613 struct dcerpc_binding_handle *b = cli->binding_handle;
615 ZERO_STRUCT(devmode_ctr);
616 ZERO_STRUCT(secdesc_ctr);
618 if (argc == 1 || argc > 3) {
619 printf("Usage: %s printername new_printername\n", argv[0]);
621 return WERR_OK;
624 /* Open a printer handle */
625 if (argc == 3) {
626 new_printername = argv[2];
629 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
631 /* get a printer handle */
632 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
633 printername,
634 PRINTER_ALL_ACCESS,
635 &pol);
636 if (!W_ERROR_IS_OK(result))
637 goto done;
639 /* Get printer info */
640 result = rpccli_spoolss_getprinter(cli, mem_ctx,
641 &pol,
642 info_level,
644 &info);
645 if (!W_ERROR_IS_OK(result))
646 goto done;
648 /* Modify the printername. */
649 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
650 info2.printername = new_printername;
652 info_ctr.level = 2;
653 info_ctr.info.info2 = &info2;
655 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
656 &pol,
657 &info_ctr,
658 &devmode_ctr,
659 &secdesc_ctr,
660 0, /* command */
661 &result);
662 if (!NT_STATUS_IS_OK(status)) {
663 result = ntstatus_to_werror(status);
664 goto done;
666 if (W_ERROR_IS_OK(result))
667 printf("Success in setting printername.\n");
669 done:
670 if (is_valid_policy_hnd(&pol)) {
671 WERROR _result;
672 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
675 return result;
678 /****************************************************************************
679 ****************************************************************************/
681 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
682 TALLOC_CTX *mem_ctx,
683 int argc, const char **argv)
685 struct policy_handle pol;
686 WERROR result;
687 uint32_t level = 1;
688 const char *printername;
689 union spoolss_PrinterInfo info;
690 struct dcerpc_binding_handle *b = cli->binding_handle;
692 if (argc == 1 || argc > 3) {
693 printf("Usage: %s <printername> [level]\n", argv[0]);
694 return WERR_OK;
697 /* Open a printer handle */
698 if (argc == 3) {
699 level = atoi(argv[2]);
702 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
704 /* get a printer handle */
706 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
707 printername,
708 SEC_FLAG_MAXIMUM_ALLOWED,
709 &pol);
710 if (!W_ERROR_IS_OK(result)) {
711 goto done;
714 /* Get printer info */
716 result = rpccli_spoolss_getprinter(cli, mem_ctx,
717 &pol,
718 level,
720 &info);
721 if (!W_ERROR_IS_OK(result)) {
722 goto done;
725 /* Display printer info */
726 switch (level) {
727 case 0:
728 display_print_info0(&info.info0);
729 break;
730 case 1:
731 display_print_info1(&info.info1);
732 break;
733 case 2:
734 display_print_info2(&info.info2);
735 break;
736 case 3:
737 display_print_info3(&info.info3);
738 break;
739 case 4:
740 display_print_info4(&info.info4);
741 break;
742 case 5:
743 display_print_info5(&info.info5);
744 break;
745 case 6:
746 display_print_info6(&info.info6);
747 break;
748 case 7:
749 display_print_info7(&info.info7);
750 break;
751 default:
752 printf("unknown info level %d\n", level);
753 break;
755 done:
756 if (is_valid_policy_hnd(&pol)) {
757 WERROR _result;
758 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
761 return result;
764 /****************************************************************************
765 ****************************************************************************/
767 static void display_reg_value(struct regval_blob *value)
769 const char *text = NULL;
770 DATA_BLOB blob;
772 switch(regval_type(value)) {
773 case REG_DWORD:
774 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
775 *((uint32_t *) regval_data_p(value)));
776 break;
777 case REG_SZ:
778 blob = data_blob_const(regval_data_p(value), regval_size(value));
779 pull_reg_sz(talloc_tos(), &blob, &text);
780 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
781 break;
782 case REG_BINARY: {
783 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
784 size_t i, len;
785 printf("%s: REG_BINARY:", regval_name(value));
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;
803 blob = data_blob_const(regval_data_p(value), regval_size(value));
805 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
806 d_printf("pull_reg_multi_sz failed\n");
807 break;
810 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
811 for (i=0; values[i] != NULL; i++) {
812 d_printf("%s\n", values[i]);
814 TALLOC_FREE(values);
815 break;
817 default:
818 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
823 /****************************************************************************
824 ****************************************************************************/
826 static void display_printer_data(const char *v,
827 enum winreg_Type type,
828 uint8_t *data,
829 uint32_t length)
831 int i;
832 union spoolss_PrinterData r;
833 DATA_BLOB blob = data_blob_const(data, length);
834 WERROR result;
836 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
837 if (!W_ERROR_IS_OK(result)) {
838 return;
841 switch (type) {
842 case REG_DWORD:
843 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
844 break;
845 case REG_SZ:
846 printf("%s: REG_SZ: %s\n", v, r.string);
847 break;
848 case REG_BINARY: {
849 char *hex = hex_encode_talloc(NULL,
850 r.binary.data, r.binary.length);
851 size_t len;
852 printf("%s: REG_BINARY:", v);
853 len = strlen(hex);
854 for (i=0; i<len; i++) {
855 if (hex[i] == '\0') {
856 break;
858 if (i%40 == 0) {
859 putchar('\n');
861 putchar(hex[i]);
863 TALLOC_FREE(hex);
864 putchar('\n');
865 break;
867 case REG_MULTI_SZ:
868 printf("%s: REG_MULTI_SZ: ", v);
869 for (i=0; r.string_array[i] != NULL; i++) {
870 printf("%s ", r.string_array[i]);
872 printf("\n");
873 break;
874 default:
875 printf("%s: unknown type 0x%02x:\n", v, type);
876 break;
880 /****************************************************************************
881 ****************************************************************************/
883 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
884 TALLOC_CTX *mem_ctx,
885 int argc, const char **argv)
887 struct policy_handle pol;
888 WERROR result;
889 fstring printername;
890 const char *valuename;
891 enum winreg_Type type;
892 uint8_t *data;
893 uint32_t needed;
894 struct dcerpc_binding_handle *b = cli->binding_handle;
896 if (argc != 3) {
897 printf("Usage: %s <printername> <valuename>\n", argv[0]);
898 printf("<printername> of . queries print server\n");
899 return WERR_OK;
901 valuename = argv[2];
903 /* Open a printer handle */
905 if (strncmp(argv[1], ".", sizeof(".")) == 0)
906 fstrcpy(printername, cli->srv_name_slash);
907 else
908 slprintf(printername, sizeof(printername)-1, "%s\\%s",
909 cli->srv_name_slash, argv[1]);
911 /* get a printer handle */
913 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
914 printername,
915 SEC_FLAG_MAXIMUM_ALLOWED,
916 &pol);
917 if (!W_ERROR_IS_OK(result))
918 goto done;
920 /* Get printer info */
922 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
923 &pol,
924 valuename,
926 &type,
927 &needed,
928 &data);
929 if (!W_ERROR_IS_OK(result))
930 goto done;
932 /* Display printer data */
934 display_printer_data(valuename, type, data, needed);
936 done:
937 if (is_valid_policy_hnd(&pol)) {
938 WERROR _result;
939 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
942 return result;
945 /****************************************************************************
946 ****************************************************************************/
948 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
949 TALLOC_CTX *mem_ctx,
950 int argc, const char **argv)
952 struct policy_handle pol;
953 WERROR result;
954 NTSTATUS status;
955 fstring printername;
956 const char *valuename, *keyname;
958 enum winreg_Type type;
959 uint8_t *data = NULL;
960 uint32_t offered = 0;
961 uint32_t needed;
962 struct dcerpc_binding_handle *b = cli->binding_handle;
964 if (argc != 4) {
965 printf("Usage: %s <printername> <keyname> <valuename>\n",
966 argv[0]);
967 printf("<printername> of . queries print server\n");
968 return WERR_OK;
970 valuename = argv[3];
971 keyname = argv[2];
973 /* Open a printer handle */
975 if (strncmp(argv[1], ".", sizeof(".")) == 0)
976 fstrcpy(printername, cli->srv_name_slash);
977 else
978 slprintf(printername, sizeof(printername)-1, "%s\\%s",
979 cli->srv_name_slash, argv[1]);
981 /* get a printer handle */
983 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
984 printername,
985 SEC_FLAG_MAXIMUM_ALLOWED,
986 &pol);
987 if (!W_ERROR_IS_OK(result))
988 goto done;
990 /* Get printer info */
992 data = talloc_zero_array(mem_ctx, uint8_t, offered);
993 if (!data) {
994 goto done;
997 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
998 &pol,
999 keyname,
1000 valuename,
1001 &type,
1002 data,
1003 offered,
1004 &needed,
1005 &result);
1006 if (!NT_STATUS_IS_OK(status)) {
1007 result = ntstatus_to_werror(status);
1008 goto done;
1010 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1011 offered = needed;
1012 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1013 if (!data) {
1014 goto done;
1016 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1017 &pol,
1018 keyname,
1019 valuename,
1020 &type,
1021 data,
1022 offered,
1023 &needed,
1024 &result);
1027 if (!NT_STATUS_IS_OK(status)) {
1028 result = ntstatus_to_werror(status);
1029 goto done;
1032 if (!W_ERROR_IS_OK(result))
1033 goto done;
1035 /* Display printer data */
1037 display_printer_data(valuename, type, data, needed);
1040 done:
1041 if (is_valid_policy_hnd(&pol)) {
1042 WERROR _result;
1043 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1046 return result;
1049 /****************************************************************************
1050 ****************************************************************************/
1052 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1054 if (!r) {
1055 return;
1058 printf("Printer Driver Info 1:\n");
1059 printf("\tDriver Name: [%s]\n", r->driver_name);
1060 printf("\n");
1063 /****************************************************************************
1064 ****************************************************************************/
1066 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1068 if (!r) {
1069 return;
1072 printf("Printer Driver Info 2:\n");
1073 printf("\tVersion: [%x]\n", r->version);
1074 printf("\tDriver Name: [%s]\n", r->driver_name);
1075 printf("\tArchitecture: [%s]\n", r->architecture);
1076 printf("\tDriver Path: [%s]\n", r->driver_path);
1077 printf("\tDatafile: [%s]\n", r->data_file);
1078 printf("\tConfigfile: [%s]\n", r->config_file);
1079 printf("\n");
1082 /****************************************************************************
1083 ****************************************************************************/
1085 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1087 int i;
1089 if (!r) {
1090 return;
1093 printf("Printer Driver Info 3:\n");
1094 printf("\tVersion: [%x]\n", r->version);
1095 printf("\tDriver Name: [%s]\n", r->driver_name);
1096 printf("\tArchitecture: [%s]\n", r->architecture);
1097 printf("\tDriver Path: [%s]\n", r->driver_path);
1098 printf("\tDatafile: [%s]\n", r->data_file);
1099 printf("\tConfigfile: [%s]\n", r->config_file);
1100 printf("\tHelpfile: [%s]\n", r->help_file);
1102 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1103 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1106 printf("\tMonitorname: [%s]\n", r->monitor_name);
1107 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1108 printf("\n");
1111 /****************************************************************************
1112 ****************************************************************************/
1114 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1116 int i;
1118 if (!r) {
1119 return;
1122 printf("Printer Driver Info 4:\n");
1123 printf("\tVersion: [%x]\n", r->version);
1124 printf("\tDriver Name: [%s]\n", r->driver_name);
1125 printf("\tArchitecture: [%s]\n", r->architecture);
1126 printf("\tDriver Path: [%s]\n", r->driver_path);
1127 printf("\tDatafile: [%s]\n", r->data_file);
1128 printf("\tConfigfile: [%s]\n", r->config_file);
1129 printf("\tHelpfile: [%s]\n", r->help_file);
1131 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1132 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1135 printf("\tMonitorname: [%s]\n", r->monitor_name);
1136 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1138 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1139 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1141 printf("\n");
1144 /****************************************************************************
1145 ****************************************************************************/
1147 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1149 if (!r) {
1150 return;
1153 printf("Printer Driver Info 5:\n");
1154 printf("\tVersion: [%x]\n", r->version);
1155 printf("\tDriver Name: [%s]\n", r->driver_name);
1156 printf("\tArchitecture: [%s]\n", r->architecture);
1157 printf("\tDriver Path: [%s]\n", r->driver_path);
1158 printf("\tDatafile: [%s]\n", r->data_file);
1159 printf("\tConfigfile: [%s]\n", r->config_file);
1160 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1161 printf("\tConfig Version: [0x%x]\n", r->config_version);
1162 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1163 printf("\n");
1166 /****************************************************************************
1167 ****************************************************************************/
1169 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1171 int i;
1173 if (!r) {
1174 return;
1177 printf("Printer Driver Info 6:\n");
1178 printf("\tVersion: [%x]\n", r->version);
1179 printf("\tDriver Name: [%s]\n", r->driver_name);
1180 printf("\tArchitecture: [%s]\n", r->architecture);
1181 printf("\tDriver Path: [%s]\n", r->driver_path);
1182 printf("\tDatafile: [%s]\n", r->data_file);
1183 printf("\tConfigfile: [%s]\n", r->config_file);
1184 printf("\tHelpfile: [%s]\n", r->help_file);
1186 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1187 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1190 printf("\tMonitorname: [%s]\n", r->monitor_name);
1191 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1193 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1194 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1197 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1198 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1199 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1200 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1201 printf("\tHardware ID: [%s]\n", r->hardware_id);
1202 printf("\tProvider: [%s]\n", r->provider);
1204 printf("\n");
1207 /****************************************************************************
1208 ****************************************************************************/
1210 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1212 int i;
1214 if (!r) {
1215 return;
1218 printf("Printer Driver Info 8:\n");
1219 printf("\tVersion: [%x]\n", r->version);
1220 printf("\tDriver Name: [%s]\n", r->driver_name);
1221 printf("\tArchitecture: [%s]\n", r->architecture);
1222 printf("\tDriver Path: [%s]\n", r->driver_path);
1223 printf("\tDatafile: [%s]\n", r->data_file);
1224 printf("\tConfigfile: [%s]\n", r->config_file);
1225 printf("\tHelpfile: [%s]\n", r->help_file);
1226 printf("\tMonitorname: [%s]\n", r->monitor_name);
1227 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1229 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1230 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1233 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1234 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1237 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1238 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1239 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1240 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1241 printf("\tHardware ID: [%s]\n", r->hardware_id);
1242 printf("\tProvider: [%s]\n", r->provider);
1243 printf("\tPrint Processor: [%s]\n", r->print_processor);
1244 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1245 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1246 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1248 printf("\tInf Path: [%s]\n", r->inf_path);
1249 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1250 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1251 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1253 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1254 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1255 (long long unsigned int)r->min_inbox_driver_ver_version);
1257 printf("\n");
1260 /****************************************************************************
1261 ****************************************************************************/
1263 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1264 TALLOC_CTX *mem_ctx,
1265 int argc, const char **argv)
1267 struct policy_handle pol;
1268 WERROR werror;
1269 uint32_t level = 3;
1270 const char *printername;
1271 uint32_t i;
1272 bool success = false;
1273 union spoolss_DriverInfo info;
1274 uint32_t server_major_version;
1275 uint32_t server_minor_version;
1276 struct dcerpc_binding_handle *b = cli->binding_handle;
1278 if ((argc == 1) || (argc > 3)) {
1279 printf("Usage: %s <printername> [level]\n", argv[0]);
1280 return WERR_OK;
1283 /* get the arguments need to open the printer handle */
1285 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1287 if (argc == 3) {
1288 level = atoi(argv[2]);
1291 /* Open a printer handle */
1293 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1294 printername,
1295 PRINTER_ACCESS_USE,
1296 &pol);
1297 if (!W_ERROR_IS_OK(werror)) {
1298 printf("Error opening printer handle for %s!\n", printername);
1299 return werror;
1302 /* loop through and print driver info level for each architecture */
1304 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1306 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1307 &pol,
1308 archi_table[i].long_archi,
1309 level,
1310 0, /* offered */
1311 archi_table[i].version,
1313 &info,
1314 &server_major_version,
1315 &server_minor_version);
1316 if (!W_ERROR_IS_OK(werror)) {
1317 continue;
1320 /* need at least one success */
1322 success = true;
1324 printf("\n[%s]\n", archi_table[i].long_archi);
1326 switch (level) {
1327 case 1:
1328 display_print_driver1(&info.info1);
1329 break;
1330 case 2:
1331 display_print_driver2(&info.info2);
1332 break;
1333 case 3:
1334 display_print_driver3(&info.info3);
1335 break;
1336 case 4:
1337 display_print_driver4(&info.info4);
1338 break;
1339 case 5:
1340 display_print_driver5(&info.info5);
1341 break;
1342 case 6:
1343 display_print_driver6(&info.info6);
1344 break;
1345 case 8:
1346 display_print_driver8(&info.info8);
1347 break;
1348 default:
1349 printf("unknown info level %d\n", level);
1350 break;
1354 /* Cleanup */
1356 if (is_valid_policy_hnd(&pol)) {
1357 WERROR _result;
1358 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1361 if (success) {
1362 werror = WERR_OK;
1365 return werror;
1368 /****************************************************************************
1369 ****************************************************************************/
1371 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1372 TALLOC_CTX *mem_ctx,
1373 const char *architecture,
1374 uint32_t level)
1376 WERROR werror;
1377 uint32_t count = 0;
1378 union spoolss_DriverInfo *info = NULL;
1379 uint32_t j;
1381 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1382 cli->srv_name_slash,
1383 architecture,
1384 level,
1386 &count,
1387 &info);
1389 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1390 printf("Server does not support environment [%s]\n",
1391 architecture);
1392 return WERR_OK;
1395 if (count == 0) {
1396 return WERR_OK;
1399 if (!W_ERROR_IS_OK(werror)) {
1400 printf("Error getting driver for environment [%s] - %s\n",
1401 architecture, win_errstr(werror));
1402 return werror;
1405 printf("\n[%s]\n", architecture);
1407 switch (level) {
1408 case 1:
1409 for (j=0; j < count; j++) {
1410 display_print_driver1(&info[j].info1);
1412 break;
1413 case 2:
1414 for (j=0; j < count; j++) {
1415 display_print_driver2(&info[j].info2);
1417 break;
1418 case 3:
1419 for (j=0; j < count; j++) {
1420 display_print_driver3(&info[j].info3);
1422 break;
1423 case 4:
1424 for (j=0; j < count; j++) {
1425 display_print_driver4(&info[j].info4);
1427 break;
1428 case 5:
1429 for (j=0; j < count; j++) {
1430 display_print_driver5(&info[j].info5);
1432 break;
1433 case 6:
1434 for (j=0; j < count; j++) {
1435 display_print_driver6(&info[j].info6);
1437 break;
1438 case 8:
1439 for (j=0; j < count; j++) {
1440 display_print_driver8(&info[j].info8);
1442 break;
1443 default:
1444 printf("unknown info level %d\n", level);
1445 return WERR_UNKNOWN_LEVEL;
1448 return werror;
1451 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1452 TALLOC_CTX *mem_ctx,
1453 int argc, const char **argv)
1455 WERROR werror = WERR_OK;
1456 uint32_t level = 1;
1457 uint32_t i;
1458 const char *architecture = NULL;
1460 if (argc > 3) {
1461 printf("Usage: enumdrivers [level] [architecture]\n");
1462 return WERR_OK;
1465 if (argc >= 2) {
1466 level = atoi(argv[1]);
1469 if (argc == 3) {
1470 architecture = argv[2];
1473 if (architecture) {
1474 return enum_driver_by_architecture(cli, mem_ctx,
1475 architecture,
1476 level);
1479 /* loop through and print driver info level for each architecture */
1480 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1481 /* check to see if we already asked for this architecture string */
1483 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1484 continue;
1487 werror = enum_driver_by_architecture(cli, mem_ctx,
1488 archi_table[i].long_archi,
1489 level);
1490 if (!W_ERROR_IS_OK(werror)) {
1491 break;
1495 return werror;
1498 /****************************************************************************
1499 ****************************************************************************/
1501 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1503 printf("\tDirectory Name:[%s]\n", r->directory_name);
1506 /****************************************************************************
1507 ****************************************************************************/
1509 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1510 TALLOC_CTX *mem_ctx,
1511 int argc, const char **argv)
1513 WERROR result;
1514 NTSTATUS status;
1515 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1516 DATA_BLOB buffer;
1517 uint32_t offered;
1518 union spoolss_DriverDirectoryInfo info;
1519 uint32_t needed;
1520 struct dcerpc_binding_handle *b = cli->binding_handle;
1522 if (argc > 2) {
1523 printf("Usage: %s [environment]\n", argv[0]);
1524 return WERR_OK;
1527 /* Get the arguments need to open the printer handle */
1529 if (argc == 2) {
1530 env = argv[1];
1533 /* Get the directory. Only use Info level 1 */
1535 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1536 cli->srv_name_slash,
1537 env,
1539 NULL, /* buffer */
1540 0, /* offered */
1541 NULL, /* info */
1542 &needed,
1543 &result);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 return ntstatus_to_werror(status);
1547 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1548 offered = needed;
1549 buffer = data_blob_talloc_zero(mem_ctx, needed);
1551 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1552 cli->srv_name_slash,
1553 env,
1555 &buffer,
1556 offered,
1557 &info,
1558 &needed,
1559 &result);
1560 if (!NT_STATUS_IS_OK(status)) {
1561 return ntstatus_to_werror(status);
1565 if (W_ERROR_IS_OK(result)) {
1566 display_printdriverdir_1(&info.info1);
1569 return result;
1572 /****************************************************************************
1573 ****************************************************************************/
1575 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1576 struct spoolss_AddDriverInfo3 *info,
1577 const char *arch)
1580 int i;
1582 for (i=0; archi_table[i].long_archi != NULL; i++)
1584 if (strcmp(arch, archi_table[i].short_archi) == 0)
1586 info->version = archi_table[i].version;
1587 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1588 break;
1592 if (archi_table[i].long_archi == NULL)
1594 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1597 return;
1601 /**************************************************************************
1602 wrapper for strtok to get the next parameter from a delimited list.
1603 Needed to handle the empty parameter string denoted by "NULL"
1604 *************************************************************************/
1606 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1607 const char *delim, const char **dest,
1608 char **saveptr)
1610 char *ptr;
1612 /* get the next token */
1613 ptr = strtok_r(str, delim, saveptr);
1615 /* a string of 'NULL' is used to represent an empty
1616 parameter because two consecutive delimiters
1617 will not return an empty string. See man strtok(3)
1618 for details */
1619 if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1620 ptr = NULL;
1623 if (dest != NULL) {
1624 *dest = talloc_strdup(mem_ctx, ptr);
1627 return ptr;
1630 /********************************************************************************
1631 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1632 string in the form of
1633 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1634 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1635 <Default Data Type>:<Comma Separated list of Files>
1636 *******************************************************************************/
1638 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1639 char *args)
1641 char *str, *str2;
1642 int count = 0;
1643 char *saveptr = NULL;
1644 struct spoolss_StringArray *deps;
1645 const char **file_array = NULL;
1646 int i;
1648 /* fill in the UNISTR fields */
1649 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1650 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1651 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1652 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1653 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1654 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1655 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1657 /* <Comma Separated List of Dependent Files> */
1658 /* save the beginning of the string */
1659 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1660 str = str2;
1662 /* begin to strip out each filename */
1663 str = strtok_r(str, ",", &saveptr);
1665 /* no dependent files, we are done */
1666 if (!str) {
1667 return true;
1670 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1671 if (!deps) {
1672 return false;
1675 while (str != NULL) {
1676 add_string_to_array(deps, str, &file_array, &count);
1677 str = strtok_r(NULL, ",", &saveptr);
1680 deps->string = talloc_zero_array(deps, const char *, count + 1);
1681 if (!deps->string) {
1682 return false;
1685 for (i=0; i < count; i++) {
1686 deps->string[i] = file_array[i];
1689 r->dependent_files = deps;
1691 return true;
1694 /****************************************************************************
1695 ****************************************************************************/
1697 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1698 TALLOC_CTX *mem_ctx,
1699 int argc, const char **argv)
1701 WERROR result;
1702 NTSTATUS status;
1703 uint32_t level = 3;
1704 struct spoolss_AddDriverInfoCtr info_ctr;
1705 struct spoolss_AddDriverInfo3 info3;
1706 const char *arch;
1707 char *driver_args;
1708 struct dcerpc_binding_handle *b = cli->binding_handle;
1710 /* parse the command arguments */
1711 if (argc != 3 && argc != 4)
1713 printf ("Usage: %s <Environment> \\\n", argv[0]);
1714 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1715 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1716 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1717 printf ("\t[version]\n");
1719 return WERR_OK;
1722 /* Fill in the spoolss_AddDriverInfo3 struct */
1723 ZERO_STRUCT(info3);
1725 arch = cmd_spoolss_get_short_archi(argv[1]);
1726 if (!arch) {
1727 printf ("Error Unknown architecture [%s]\n", argv[1]);
1728 return WERR_INVALID_PARAM;
1731 set_drv_info_3_env(mem_ctx, &info3, arch);
1733 driver_args = talloc_strdup( mem_ctx, argv[2] );
1734 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1736 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1737 return WERR_INVALID_PARAM;
1740 /* if printer driver version specified, override the default version
1741 * used by the architecture. This allows installation of Windows
1742 * 2000 (version 3) printer drivers. */
1743 if (argc == 4)
1745 info3.version = atoi(argv[3]);
1749 info_ctr.level = level;
1750 info_ctr.info.info3 = &info3;
1752 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1753 cli->srv_name_slash,
1754 &info_ctr,
1755 &result);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 return ntstatus_to_werror(status);
1759 if (W_ERROR_IS_OK(result)) {
1760 printf ("Printer Driver %s successfully installed.\n",
1761 info3.driver_name);
1764 return result;
1768 /****************************************************************************
1769 ****************************************************************************/
1771 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1772 TALLOC_CTX *mem_ctx,
1773 int argc, const char **argv)
1775 WERROR result;
1776 struct spoolss_SetPrinterInfoCtr info_ctr;
1777 struct spoolss_SetPrinterInfo2 info2;
1779 /* parse the command arguments */
1780 if (argc != 5)
1782 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1783 return WERR_OK;
1786 /* Fill in the DRIVER_INFO_2 struct */
1787 ZERO_STRUCT(info2);
1789 info2.printername = argv[1];
1790 info2.drivername = argv[3];
1791 info2.sharename = argv[2];
1792 info2.portname = argv[4];
1793 info2.comment = "Created by rpcclient";
1794 info2.printprocessor = "winprint";
1795 info2.datatype = "RAW";
1796 info2.devmode_ptr = 0;
1797 info2.secdesc_ptr = 0;
1798 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1799 info2.priority = 0;
1800 info2.defaultpriority = 0;
1801 info2.starttime = 0;
1802 info2.untiltime = 0;
1804 /* These three fields must not be used by AddPrinter()
1805 as defined in the MS Platform SDK documentation..
1806 --jerry
1807 info2.status = 0;
1808 info2.cjobs = 0;
1809 info2.averageppm = 0;
1812 info_ctr.level = 2;
1813 info_ctr.info.info2 = &info2;
1815 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1816 &info_ctr);
1817 if (W_ERROR_IS_OK(result))
1818 printf ("Printer %s successfully installed.\n", argv[1]);
1820 return result;
1823 /****************************************************************************
1824 ****************************************************************************/
1826 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1827 TALLOC_CTX *mem_ctx,
1828 int argc, const char **argv)
1830 struct policy_handle pol;
1831 WERROR result;
1832 NTSTATUS status;
1833 uint32_t level = 2;
1834 const char *printername;
1835 union spoolss_PrinterInfo info;
1836 struct spoolss_SetPrinterInfoCtr info_ctr;
1837 struct spoolss_SetPrinterInfo2 info2;
1838 struct spoolss_DevmodeContainer devmode_ctr;
1839 struct sec_desc_buf secdesc_ctr;
1840 struct dcerpc_binding_handle *b = cli->binding_handle;
1842 ZERO_STRUCT(devmode_ctr);
1843 ZERO_STRUCT(secdesc_ctr);
1845 /* parse the command arguments */
1846 if (argc != 3)
1848 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1849 return WERR_OK;
1852 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1854 /* Get a printer handle */
1856 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1857 printername,
1858 PRINTER_ALL_ACCESS,
1859 &pol);
1860 if (!W_ERROR_IS_OK(result))
1861 goto done;
1863 /* Get printer info */
1865 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1866 &pol,
1867 level,
1869 &info);
1870 if (!W_ERROR_IS_OK(result)) {
1871 printf ("Unable to retrieve printer information!\n");
1872 goto done;
1875 /* Set the printer driver */
1877 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1878 info2.drivername = argv[2];
1880 info_ctr.level = 2;
1881 info_ctr.info.info2 = &info2;
1883 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1884 &pol,
1885 &info_ctr,
1886 &devmode_ctr,
1887 &secdesc_ctr,
1888 0, /* command */
1889 &result);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 result = ntstatus_to_werror(status);
1892 goto done;
1894 if (!W_ERROR_IS_OK(result)) {
1895 printf("SetPrinter call failed!\n");
1896 goto done;
1899 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1901 done:
1902 /* Cleanup */
1904 if (is_valid_policy_hnd(&pol)) {
1905 WERROR _result;
1906 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1909 return result;
1913 /****************************************************************************
1914 ****************************************************************************/
1916 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1917 TALLOC_CTX *mem_ctx,
1918 int argc, const char **argv)
1920 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1921 NTSTATUS status;
1922 struct dcerpc_binding_handle *b = cli->binding_handle;
1924 int i;
1925 int vers = -1;
1927 const char *arch = NULL;
1928 uint32_t delete_flags = 0;
1930 /* parse the command arguments */
1931 if (argc < 2 || argc > 4) {
1932 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1933 return WERR_OK;
1936 if (argc >= 3)
1937 arch = argv[2];
1938 if (argc == 4)
1939 vers = atoi (argv[3]);
1941 if (vers >= 0) {
1942 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1945 /* delete the driver for all architectures */
1946 for (i=0; archi_table[i].long_archi; i++) {
1948 if (arch && !strequal( archi_table[i].long_archi, arch))
1949 continue;
1951 if (vers >= 0 && archi_table[i].version != vers)
1952 continue;
1954 /* make the call to remove the driver */
1955 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1956 cli->srv_name_slash,
1957 archi_table[i].long_archi,
1958 argv[1],
1959 delete_flags,
1960 archi_table[i].version,
1961 &result);
1962 if (!NT_STATUS_IS_OK(status)) {
1963 return ntstatus_to_werror(status);
1965 if ( !W_ERROR_IS_OK(result) )
1967 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1968 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1969 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1972 else
1974 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1975 archi_table[i].long_archi, archi_table[i].version);
1976 ret = WERR_OK;
1980 return ret;
1984 /****************************************************************************
1985 ****************************************************************************/
1987 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1988 TALLOC_CTX *mem_ctx,
1989 int argc, const char **argv)
1991 WERROR result = WERR_OK;
1992 NTSTATUS status;
1993 int i;
1994 struct dcerpc_binding_handle *b = cli->binding_handle;
1996 /* parse the command arguments */
1997 if (argc != 2) {
1998 printf ("Usage: %s <driver>\n", argv[0]);
1999 return WERR_OK;
2002 /* delete the driver for all architectures */
2003 for (i=0; archi_table[i].long_archi; i++) {
2004 result = WERR_OK;
2006 /* make the call to remove the driver */
2007 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2008 cli->srv_name_slash,
2009 archi_table[i].long_archi,
2010 argv[1],
2011 &result);
2012 if (!NT_STATUS_IS_OK(status)) {
2013 result = ntstatus_to_werror(status);
2014 continue;
2016 if ( !W_ERROR_IS_OK(result) ) {
2017 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2018 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2019 argv[1], archi_table[i].long_archi,
2020 win_errstr(result));
2022 } else {
2023 printf ("Driver %s removed for arch [%s].\n", argv[1],
2024 archi_table[i].long_archi);
2028 return result;
2031 /****************************************************************************
2032 ****************************************************************************/
2034 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2035 TALLOC_CTX *mem_ctx,
2036 int argc, const char **argv)
2038 WERROR result;
2039 NTSTATUS status;
2040 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2041 DATA_BLOB buffer;
2042 uint32_t offered;
2043 union spoolss_PrintProcessorDirectoryInfo info;
2044 uint32_t needed;
2045 struct dcerpc_binding_handle *b = cli->binding_handle;
2047 /* parse the command arguments */
2048 if (argc > 2) {
2049 printf ("Usage: %s [environment]\n", argv[0]);
2050 return WERR_OK;
2053 if (argc == 2) {
2054 environment = argv[1];
2057 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2058 cli->srv_name_slash,
2059 environment,
2061 NULL, /* buffer */
2062 0, /* offered */
2063 NULL, /* info */
2064 &needed,
2065 &result);
2066 if (!NT_STATUS_IS_OK(status)) {
2067 return ntstatus_to_werror(status);
2069 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2070 offered = needed;
2071 buffer = data_blob_talloc_zero(mem_ctx, needed);
2073 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2074 cli->srv_name_slash,
2075 environment,
2077 &buffer,
2078 offered,
2079 &info,
2080 &needed,
2081 &result);
2082 if (!NT_STATUS_IS_OK(status)) {
2083 return ntstatus_to_werror(status);
2087 if (W_ERROR_IS_OK(result)) {
2088 printf("%s\n", info.info1.directory_name);
2091 return result;
2094 /****************************************************************************
2095 ****************************************************************************/
2097 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2098 int argc, const char **argv)
2100 struct policy_handle handle;
2101 WERROR werror;
2102 NTSTATUS status;
2103 const char *printername;
2104 union spoolss_AddFormInfo info;
2105 struct spoolss_AddFormInfo1 info1;
2106 struct spoolss_AddFormInfo2 info2;
2107 uint32_t level = 1;
2108 struct dcerpc_binding_handle *b = cli->binding_handle;
2110 /* Parse the command arguments */
2112 if (argc < 3 || argc > 5) {
2113 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2114 return WERR_OK;
2117 /* Get a printer handle */
2119 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2121 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2122 printername,
2123 PRINTER_ALL_ACCESS,
2124 &handle);
2125 if (!W_ERROR_IS_OK(werror))
2126 goto done;
2128 /* Dummy up some values for the form data */
2130 if (argc == 4) {
2131 level = atoi(argv[3]);
2134 switch (level) {
2135 case 1:
2136 info1.flags = SPOOLSS_FORM_USER;
2137 info1.form_name = argv[2];
2138 info1.size.width = 100;
2139 info1.size.height = 100;
2140 info1.area.left = 0;
2141 info1.area.top = 10;
2142 info1.area.right = 20;
2143 info1.area.bottom = 30;
2145 info.info1 = &info1;
2147 break;
2148 case 2:
2149 info2.flags = SPOOLSS_FORM_USER;
2150 info2.form_name = argv[2];
2151 info2.size.width = 100;
2152 info2.size.height = 100;
2153 info2.area.left = 0;
2154 info2.area.top = 10;
2155 info2.area.right = 20;
2156 info2.area.bottom = 30;
2157 info2.keyword = argv[2];
2158 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2159 info2.mui_dll = NULL;
2160 info2.ressource_id = 0;
2161 info2.display_name = argv[2];
2162 info2.lang_id = 0;
2164 info.info2 = &info2;
2166 break;
2167 default:
2168 werror = WERR_INVALID_PARAM;
2169 goto done;
2172 /* Add the form */
2175 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2176 &handle,
2177 level,
2178 info,
2179 &werror);
2180 if (!NT_STATUS_IS_OK(status)) {
2181 werror = ntstatus_to_werror(status);
2182 goto done;
2184 done:
2185 if (is_valid_policy_hnd(&handle)) {
2186 WERROR _result;
2187 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2190 return werror;
2193 /****************************************************************************
2194 ****************************************************************************/
2196 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2197 int argc, const char **argv)
2199 struct policy_handle handle;
2200 WERROR werror;
2201 NTSTATUS status;
2202 const char *printername;
2203 union spoolss_AddFormInfo info;
2204 struct spoolss_AddFormInfo1 info1;
2205 struct dcerpc_binding_handle *b = cli->binding_handle;
2207 /* Parse the command arguments */
2209 if (argc != 3) {
2210 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2211 return WERR_OK;
2214 /* Get a printer handle */
2216 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2218 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2219 printername,
2220 SEC_FLAG_MAXIMUM_ALLOWED,
2221 &handle);
2222 if (!W_ERROR_IS_OK(werror))
2223 goto done;
2225 /* Dummy up some values for the form data */
2227 info1.flags = SPOOLSS_FORM_PRINTER;
2228 info1.size.width = 100;
2229 info1.size.height = 100;
2230 info1.area.left = 0;
2231 info1.area.top = 1000;
2232 info1.area.right = 2000;
2233 info1.area.bottom = 3000;
2234 info1.form_name = argv[2];
2236 info.info1 = &info1;
2238 /* Set the form */
2240 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2241 &handle,
2242 argv[2],
2244 info,
2245 &werror);
2246 if (!NT_STATUS_IS_OK(status)) {
2247 werror = ntstatus_to_werror(status);
2248 goto done;
2250 done:
2251 if (is_valid_policy_hnd(&handle)) {
2252 WERROR _result;
2253 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2256 return werror;
2259 /****************************************************************************
2260 ****************************************************************************/
2262 static const char *get_form_flag(int form_flag)
2264 switch (form_flag) {
2265 case SPOOLSS_FORM_USER:
2266 return "FORM_USER";
2267 case SPOOLSS_FORM_BUILTIN:
2268 return "FORM_BUILTIN";
2269 case SPOOLSS_FORM_PRINTER:
2270 return "FORM_PRINTER";
2271 default:
2272 return "unknown";
2276 /****************************************************************************
2277 ****************************************************************************/
2279 static void display_form_info1(struct spoolss_FormInfo1 *r)
2281 printf("%s\n" \
2282 "\tflag: %s (%d)\n" \
2283 "\twidth: %d, length: %d\n" \
2284 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2285 r->form_name, get_form_flag(r->flags), r->flags,
2286 r->size.width, r->size.height,
2287 r->area.left, r->area.right,
2288 r->area.top, r->area.bottom);
2291 /****************************************************************************
2292 ****************************************************************************/
2294 static void display_form_info2(struct spoolss_FormInfo2 *r)
2296 printf("%s\n" \
2297 "\tflag: %s (%d)\n" \
2298 "\twidth: %d, length: %d\n" \
2299 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2300 r->form_name, get_form_flag(r->flags), r->flags,
2301 r->size.width, r->size.height,
2302 r->area.left, r->area.right,
2303 r->area.top, r->area.bottom);
2304 printf("\tkeyword: %s\n", r->keyword);
2305 printf("\tstring_type: 0x%08x\n", r->string_type);
2306 printf("\tmui_dll: %s\n", r->mui_dll);
2307 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2308 printf("\tdisplay_name: %s\n", r->display_name);
2309 printf("\tlang_id: %d\n", r->lang_id);
2310 printf("\n");
2313 /****************************************************************************
2314 ****************************************************************************/
2316 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2317 int argc, const char **argv)
2319 struct policy_handle handle;
2320 WERROR werror;
2321 NTSTATUS status;
2322 const char *printername;
2323 DATA_BLOB buffer;
2324 uint32_t offered = 0;
2325 union spoolss_FormInfo info;
2326 uint32_t needed;
2327 uint32_t level = 1;
2328 struct dcerpc_binding_handle *b = cli->binding_handle;
2330 /* Parse the command arguments */
2332 if (argc < 3 || argc > 5) {
2333 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2334 return WERR_OK;
2337 /* Get a printer handle */
2339 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2341 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2342 printername,
2343 SEC_FLAG_MAXIMUM_ALLOWED,
2344 &handle);
2345 if (!W_ERROR_IS_OK(werror))
2346 goto done;
2348 if (argc == 4) {
2349 level = atoi(argv[3]);
2352 /* Get the form */
2354 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2355 &handle,
2356 argv[2],
2357 level,
2358 NULL,
2359 offered,
2360 &info,
2361 &needed,
2362 &werror);
2363 if (!NT_STATUS_IS_OK(status)) {
2364 werror = ntstatus_to_werror(status);
2365 goto done;
2367 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2368 buffer = data_blob_talloc_zero(mem_ctx, needed);
2369 offered = needed;
2370 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2371 &handle,
2372 argv[2],
2373 level,
2374 &buffer,
2375 offered,
2376 &info,
2377 &needed,
2378 &werror);
2379 if (!NT_STATUS_IS_OK(status)) {
2380 werror = ntstatus_to_werror(status);
2381 goto done;
2385 if (!W_ERROR_IS_OK(werror)) {
2386 goto done;
2389 switch (level) {
2390 case 1:
2391 display_form_info1(&info.info1);
2392 break;
2393 case 2:
2394 display_form_info2(&info.info2);
2395 break;
2398 done:
2399 if (is_valid_policy_hnd(&handle)) {
2400 WERROR _result;
2401 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2404 return werror;
2407 /****************************************************************************
2408 ****************************************************************************/
2410 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2411 TALLOC_CTX *mem_ctx, int argc,
2412 const char **argv)
2414 struct policy_handle handle;
2415 WERROR werror;
2416 NTSTATUS status;
2417 const char *printername;
2418 struct dcerpc_binding_handle *b = cli->binding_handle;
2420 /* Parse the command arguments */
2422 if (argc != 3) {
2423 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2424 return WERR_OK;
2427 /* Get a printer handle */
2429 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2431 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2432 printername,
2433 SEC_FLAG_MAXIMUM_ALLOWED,
2434 &handle);
2435 if (!W_ERROR_IS_OK(werror))
2436 goto done;
2438 /* Delete the form */
2440 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2441 &handle,
2442 argv[2],
2443 &werror);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 werror = ntstatus_to_werror(status);
2446 goto done;
2449 done:
2450 if (is_valid_policy_hnd(&handle)) {
2451 WERROR _result;
2452 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2455 return werror;
2458 /****************************************************************************
2459 ****************************************************************************/
2461 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2462 TALLOC_CTX *mem_ctx, int argc,
2463 const char **argv)
2465 struct policy_handle handle;
2466 WERROR werror;
2467 const char *printername;
2468 uint32_t num_forms, level = 1, i;
2469 union spoolss_FormInfo *forms;
2470 struct dcerpc_binding_handle *b = cli->binding_handle;
2472 /* Parse the command arguments */
2474 if (argc < 2 || argc > 4) {
2475 printf ("Usage: %s <printer> [level]\n", argv[0]);
2476 return WERR_OK;
2479 /* Get a printer handle */
2481 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2483 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2484 printername,
2485 SEC_FLAG_MAXIMUM_ALLOWED,
2486 &handle);
2487 if (!W_ERROR_IS_OK(werror))
2488 goto done;
2490 if (argc == 3) {
2491 level = atoi(argv[2]);
2494 /* Enumerate forms */
2496 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2497 &handle,
2498 level,
2500 &num_forms,
2501 &forms);
2503 if (!W_ERROR_IS_OK(werror))
2504 goto done;
2506 /* Display output */
2508 for (i = 0; i < num_forms; i++) {
2509 switch (level) {
2510 case 1:
2511 display_form_info1(&forms[i].info1);
2512 break;
2513 case 2:
2514 display_form_info2(&forms[i].info2);
2515 break;
2519 done:
2520 if (is_valid_policy_hnd(&handle)) {
2521 WERROR _result;
2522 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2525 return werror;
2528 /****************************************************************************
2529 ****************************************************************************/
2531 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2532 TALLOC_CTX *mem_ctx,
2533 int argc, const char **argv)
2535 WERROR result;
2536 NTSTATUS status;
2537 const char *printername;
2538 struct policy_handle pol;
2539 union spoolss_PrinterInfo info;
2540 enum winreg_Type type;
2541 union spoolss_PrinterData data;
2542 DATA_BLOB blob;
2543 struct dcerpc_binding_handle *b = cli->binding_handle;
2545 /* parse the command arguments */
2546 if (argc < 5) {
2547 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2548 " <value> <data>\n",
2549 argv[0]);
2550 return WERR_OK;
2553 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2555 type = REG_NONE;
2557 if (strequal(argv[2], "string")) {
2558 type = REG_SZ;
2561 if (strequal(argv[2], "binary")) {
2562 type = REG_BINARY;
2565 if (strequal(argv[2], "dword")) {
2566 type = REG_DWORD;
2569 if (strequal(argv[2], "multistring")) {
2570 type = REG_MULTI_SZ;
2573 if (type == REG_NONE) {
2574 printf("Unknown data type: %s\n", argv[2]);
2575 result = WERR_INVALID_PARAM;
2576 goto done;
2579 /* get a printer handle */
2581 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2582 printername,
2583 SEC_FLAG_MAXIMUM_ALLOWED,
2584 &pol);
2585 if (!W_ERROR_IS_OK(result)) {
2586 goto done;
2589 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2590 &pol,
2593 &info);
2594 if (!W_ERROR_IS_OK(result)) {
2595 goto done;
2598 printf("%s\n", current_timestring(mem_ctx, true));
2599 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2601 /* Set the printer data */
2603 switch (type) {
2604 case REG_SZ:
2605 data.string = talloc_strdup(mem_ctx, argv[4]);
2606 W_ERROR_HAVE_NO_MEMORY(data.string);
2607 break;
2608 case REG_DWORD:
2609 data.value = strtoul(argv[4], NULL, 10);
2610 break;
2611 case REG_BINARY:
2612 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2613 break;
2614 case REG_MULTI_SZ: {
2615 int i, num_strings;
2616 const char **strings = NULL;
2618 for (i=4; i<argc; i++) {
2619 if (strcmp(argv[i], "NULL") == 0) {
2620 argv[i] = "";
2622 if (!add_string_to_array(mem_ctx, argv[i],
2623 &strings,
2624 &num_strings)) {
2625 result = WERR_NOMEM;
2626 goto done;
2629 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2630 if (!data.string_array) {
2631 result = WERR_NOMEM;
2632 goto done;
2634 for (i=0; i < num_strings; i++) {
2635 data.string_array[i] = strings[i];
2637 break;
2639 default:
2640 printf("Unknown data type: %s\n", argv[2]);
2641 result = WERR_INVALID_PARAM;
2642 goto done;
2645 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2646 if (!W_ERROR_IS_OK(result)) {
2647 goto done;
2650 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2651 &pol,
2652 argv[3], /* value_name */
2653 type,
2654 blob.data,
2655 blob.length,
2656 &result);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2659 result = ntstatus_to_werror(status);
2660 goto done;
2662 if (!W_ERROR_IS_OK(result)) {
2663 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2664 goto done;
2666 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2668 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2669 &pol,
2672 &info);
2673 if (!W_ERROR_IS_OK(result)) {
2674 goto done;
2677 printf("%s\n", current_timestring(mem_ctx, true));
2678 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2680 done:
2681 /* cleanup */
2682 if (is_valid_policy_hnd(&pol)) {
2683 WERROR _result;
2684 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2687 return result;
2690 /****************************************************************************
2691 ****************************************************************************/
2693 static void display_job_info1(struct spoolss_JobInfo1 *r)
2695 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2696 r->user_name, r->document_name, r->text_status, r->pages_printed,
2697 r->total_pages);
2700 /****************************************************************************
2701 ****************************************************************************/
2703 static void display_job_info2(struct spoolss_JobInfo2 *r)
2705 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2706 r->position, r->job_id,
2707 r->user_name, r->document_name, r->text_status, r->pages_printed,
2708 r->total_pages, r->size);
2711 /****************************************************************************
2712 ****************************************************************************/
2714 static void display_job_info3(struct spoolss_JobInfo3 *r)
2716 printf("jobid[%d], next_jobid[%d]\n",
2717 r->job_id, r->next_job_id);
2720 /****************************************************************************
2721 ****************************************************************************/
2723 static void display_job_info4(struct spoolss_JobInfo4 *r)
2725 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2726 r->position, r->job_id,
2727 r->user_name, r->document_name, r->text_status, r->pages_printed,
2728 r->total_pages, r->size, r->size_high);
2731 /****************************************************************************
2732 ****************************************************************************/
2734 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2735 TALLOC_CTX *mem_ctx, int argc,
2736 const char **argv)
2738 WERROR result;
2739 uint32_t level = 1, count, i;
2740 const char *printername;
2741 struct policy_handle hnd;
2742 union spoolss_JobInfo *info;
2743 struct dcerpc_binding_handle *b = cli->binding_handle;
2745 if (argc < 2 || argc > 3) {
2746 printf("Usage: %s printername [level]\n", argv[0]);
2747 return WERR_OK;
2750 if (argc == 3) {
2751 level = atoi(argv[2]);
2754 /* Open printer handle */
2756 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2758 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2759 printername,
2760 SEC_FLAG_MAXIMUM_ALLOWED,
2761 &hnd);
2762 if (!W_ERROR_IS_OK(result))
2763 goto done;
2765 /* Enumerate ports */
2767 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2768 &hnd,
2769 0, /* firstjob */
2770 1000, /* numjobs */
2771 level,
2773 &count,
2774 &info);
2775 if (!W_ERROR_IS_OK(result)) {
2776 goto done;
2779 for (i = 0; i < count; i++) {
2780 switch (level) {
2781 case 1:
2782 display_job_info1(&info[i].info1);
2783 break;
2784 case 2:
2785 display_job_info2(&info[i].info2);
2786 break;
2787 default:
2788 d_printf("unknown info level %d\n", level);
2789 break;
2793 done:
2794 if (is_valid_policy_hnd(&hnd)) {
2795 WERROR _result;
2796 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2799 return result;
2802 /****************************************************************************
2803 ****************************************************************************/
2805 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2806 TALLOC_CTX *mem_ctx, int argc,
2807 const char **argv)
2809 WERROR result;
2810 const char *printername;
2811 struct policy_handle hnd;
2812 uint32_t job_id;
2813 uint32_t level = 1;
2814 union spoolss_JobInfo info;
2815 struct dcerpc_binding_handle *b = cli->binding_handle;
2817 if (argc < 3 || argc > 4) {
2818 printf("Usage: %s printername job_id [level]\n", argv[0]);
2819 return WERR_OK;
2822 job_id = atoi(argv[2]);
2824 if (argc == 4) {
2825 level = atoi(argv[3]);
2828 /* Open printer handle */
2830 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2832 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2833 printername,
2834 SEC_FLAG_MAXIMUM_ALLOWED,
2835 &hnd);
2836 if (!W_ERROR_IS_OK(result)) {
2837 goto done;
2840 /* Enumerate ports */
2842 result = rpccli_spoolss_getjob(cli, mem_ctx,
2843 &hnd,
2844 job_id,
2845 level,
2847 &info);
2849 if (!W_ERROR_IS_OK(result)) {
2850 goto done;
2853 switch (level) {
2854 case 1:
2855 display_job_info1(&info.info1);
2856 break;
2857 case 2:
2858 display_job_info2(&info.info2);
2859 break;
2860 case 3:
2861 display_job_info3(&info.info3);
2862 break;
2863 case 4:
2864 display_job_info4(&info.info4);
2865 break;
2866 default:
2867 d_printf("unknown info level %d\n", level);
2868 break;
2871 done:
2872 if (is_valid_policy_hnd(&hnd)) {
2873 WERROR _result;
2874 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2877 return result;
2880 /****************************************************************************
2881 ****************************************************************************/
2883 static struct {
2884 const char *name;
2885 enum spoolss_JobControl val;
2886 } cmdvals[] = {
2887 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2888 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2889 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2890 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2891 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2892 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2893 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2894 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2895 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2898 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2900 int i;
2902 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2903 if (strequal(cmdvals[i].name, cmd)) {
2904 return cmdvals[i].val;
2907 return (enum spoolss_JobControl)atoi(cmd);
2910 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2911 TALLOC_CTX *mem_ctx, int argc,
2912 const char **argv)
2914 WERROR result;
2915 NTSTATUS status;
2916 const char *printername;
2917 struct policy_handle hnd;
2918 uint32_t job_id;
2919 enum spoolss_JobControl command;
2920 struct dcerpc_binding_handle *b = cli->binding_handle;
2922 if (argc != 4) {
2923 printf("Usage: %s printername job_id command\n", argv[0]);
2924 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2925 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2926 return WERR_OK;
2929 job_id = atoi(argv[2]);
2930 command = parse_setjob_command(argv[3]);
2932 /* Open printer handle */
2934 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2936 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2937 printername,
2938 SEC_FLAG_MAXIMUM_ALLOWED,
2939 &hnd);
2940 if (!W_ERROR_IS_OK(result)) {
2941 goto done;
2944 /* Set Job */
2946 status = dcerpc_spoolss_SetJob(b, mem_ctx,
2947 &hnd,
2948 job_id,
2949 NULL,
2950 command,
2951 &result);
2952 if (!NT_STATUS_IS_OK(status)) {
2953 result = ntstatus_to_werror(status);
2954 goto done;
2956 if (!W_ERROR_IS_OK(result)) {
2957 goto done;
2960 done:
2961 if (is_valid_policy_hnd(&hnd)) {
2962 WERROR _result;
2963 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2966 return result;
2969 /****************************************************************************
2970 ****************************************************************************/
2972 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2973 TALLOC_CTX *mem_ctx, int argc,
2974 const char **argv)
2976 WERROR result;
2977 NTSTATUS status;
2978 const char *printername;
2979 struct policy_handle hnd;
2980 uint32_t value_needed;
2981 enum winreg_Type type;
2982 uint32_t data_needed;
2983 struct dcerpc_binding_handle *b = cli->binding_handle;
2984 struct spoolss_EnumPrinterData r;
2986 if (argc != 2) {
2987 printf("Usage: %s printername\n", argv[0]);
2988 return WERR_OK;
2991 /* Open printer handle */
2993 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2995 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2996 printername,
2997 SEC_FLAG_MAXIMUM_ALLOWED,
2998 &hnd);
2999 if (!W_ERROR_IS_OK(result)) {
3000 goto done;
3003 /* Enumerate data */
3005 r.in.handle = &hnd;
3006 r.in.enum_index = 0;
3007 r.in.value_offered = 0;
3008 r.in.data_offered = 0;
3009 r.out.value_name = NULL;
3010 r.out.value_needed = &value_needed;
3011 r.out.type = &type;
3012 r.out.data = NULL;
3013 r.out.data_needed = &data_needed;
3015 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3016 if (!NT_STATUS_IS_OK(status)) {
3017 result = ntstatus_to_werror(status);
3018 goto done;
3021 if (!W_ERROR_IS_OK(r.out.result)) {
3022 result = r.out.result;
3023 goto done;
3026 r.in.data_offered = *r.out.data_needed;
3027 r.in.value_offered = *r.out.value_needed;
3028 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3029 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3031 do {
3033 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3034 if (!NT_STATUS_IS_OK(status)) {
3035 result = ntstatus_to_werror(status);
3036 goto done;
3039 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3040 result = WERR_OK;
3041 break;
3044 r.in.enum_index++;
3047 struct regval_blob *v;
3049 v = regval_compose(talloc_tos(),
3050 r.out.value_name,
3051 *r.out.type,
3052 r.out.data,
3053 r.in.data_offered);
3054 if (v == NULL) {
3055 result = WERR_NOMEM;
3056 goto done;
3059 display_reg_value(v);
3060 talloc_free(v);
3063 } while (W_ERROR_IS_OK(r.out.result));
3065 done:
3066 if (is_valid_policy_hnd(&hnd)) {
3067 WERROR _result;
3068 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3071 return result;
3074 /****************************************************************************
3075 ****************************************************************************/
3077 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3078 TALLOC_CTX *mem_ctx, int argc,
3079 const char **argv)
3081 WERROR result;
3082 uint32_t i;
3083 const char *printername;
3084 struct policy_handle hnd;
3085 uint32_t count;
3086 struct spoolss_PrinterEnumValues *info;
3087 struct dcerpc_binding_handle *b = cli->binding_handle;
3089 if (argc != 3) {
3090 printf("Usage: %s printername <keyname>\n", argv[0]);
3091 return WERR_OK;
3094 /* Open printer handle */
3096 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3098 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3099 printername,
3100 SEC_FLAG_MAXIMUM_ALLOWED,
3101 &hnd);
3102 if (!W_ERROR_IS_OK(result)) {
3103 goto done;
3106 /* Enumerate subkeys */
3108 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3109 &hnd,
3110 argv[2],
3112 &count,
3113 &info);
3114 if (!W_ERROR_IS_OK(result)) {
3115 goto done;
3118 for (i=0; i < count; i++) {
3119 display_printer_data(info[i].value_name,
3120 info[i].type,
3121 info[i].data->data,
3122 info[i].data->length);
3125 done:
3126 if (is_valid_policy_hnd(&hnd)) {
3127 WERROR _result;
3128 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3131 return result;
3134 /****************************************************************************
3135 ****************************************************************************/
3137 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3138 TALLOC_CTX *mem_ctx, int argc,
3139 const char **argv)
3141 WERROR result;
3142 const char *printername;
3143 const char *keyname = NULL;
3144 struct policy_handle hnd;
3145 const char **key_buffer = NULL;
3146 int i;
3147 uint32_t offered = 0;
3148 struct dcerpc_binding_handle *b = cli->binding_handle;
3150 if (argc < 2 || argc > 4) {
3151 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3152 return WERR_OK;
3155 if (argc >= 3) {
3156 keyname = argv[2];
3157 } else {
3158 keyname = "";
3161 if (argc == 4) {
3162 offered = atoi(argv[3]);
3165 /* Open printer handle */
3167 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3169 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3170 printername,
3171 SEC_FLAG_MAXIMUM_ALLOWED,
3172 &hnd);
3173 if (!W_ERROR_IS_OK(result)) {
3174 goto done;
3177 /* Enumerate subkeys */
3179 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3180 &hnd,
3181 keyname,
3182 &key_buffer,
3183 offered);
3185 if (!W_ERROR_IS_OK(result)) {
3186 goto done;
3189 for (i=0; key_buffer && key_buffer[i]; i++) {
3190 printf("%s\n", key_buffer[i]);
3193 done:
3195 if (is_valid_policy_hnd(&hnd)) {
3196 WERROR _result;
3197 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3200 return result;
3203 /****************************************************************************
3204 ****************************************************************************/
3206 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3207 TALLOC_CTX *mem_ctx, int argc,
3208 const char **argv)
3210 const char *printername;
3211 const char *clientname;
3212 struct policy_handle hnd;
3213 WERROR result;
3214 NTSTATUS status;
3215 struct spoolss_NotifyOption option;
3216 struct dcerpc_binding_handle *b = cli->binding_handle;
3218 if (argc != 2) {
3219 printf("Usage: %s printername\n", argv[0]);
3220 result = WERR_OK;
3221 goto done;
3224 /* Open printer */
3226 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3228 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3229 printername,
3230 SEC_FLAG_MAXIMUM_ALLOWED,
3231 &hnd);
3232 if (!W_ERROR_IS_OK(result)) {
3233 printf("Error opening %s\n", argv[1]);
3234 goto done;
3237 /* Create spool options */
3239 option.version = 2;
3240 option.count = 2;
3242 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3243 if (option.types == NULL) {
3244 result = WERR_NOMEM;
3245 goto done;
3248 option.types[0].type = PRINTER_NOTIFY_TYPE;
3249 option.types[0].count = 1;
3250 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3251 if (option.types[0].fields == NULL) {
3252 result = WERR_NOMEM;
3253 goto done;
3255 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3257 option.types[1].type = JOB_NOTIFY_TYPE;
3258 option.types[1].count = 1;
3259 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3260 if (option.types[1].fields == NULL) {
3261 result = WERR_NOMEM;
3262 goto done;
3264 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3266 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3267 if (!clientname) {
3268 result = WERR_NOMEM;
3269 goto done;
3272 /* Send rffpcnex */
3274 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3275 &hnd,
3278 clientname,
3279 123,
3280 &option,
3281 &result);
3282 if (!NT_STATUS_IS_OK(status)) {
3283 result = ntstatus_to_werror(status);
3284 goto done;
3286 if (!W_ERROR_IS_OK(result)) {
3287 printf("Error rffpcnex %s\n", argv[1]);
3288 goto done;
3291 done:
3292 if (is_valid_policy_hnd(&hnd)) {
3293 WERROR _result;
3294 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3297 return result;
3300 /****************************************************************************
3301 ****************************************************************************/
3303 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3304 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3306 union spoolss_PrinterInfo info1, info2;
3307 WERROR werror;
3308 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3310 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3311 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3312 hnd1,
3315 &info1);
3316 if ( !W_ERROR_IS_OK(werror) ) {
3317 printf("failed (%s)\n", win_errstr(werror));
3318 talloc_destroy(mem_ctx);
3319 return false;
3321 printf("ok\n");
3323 printf("Retrieving printer properties for %s...", cli2->desthost);
3324 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3325 hnd2,
3328 &info2);
3329 if ( !W_ERROR_IS_OK(werror) ) {
3330 printf("failed (%s)\n", win_errstr(werror));
3331 talloc_destroy(mem_ctx);
3332 return false;
3334 printf("ok\n");
3336 talloc_destroy(mem_ctx);
3338 return true;
3341 /****************************************************************************
3342 ****************************************************************************/
3344 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3345 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3347 union spoolss_PrinterInfo info1, info2;
3348 WERROR werror;
3349 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3350 struct security_descriptor *sd1, *sd2;
3351 bool result = true;
3354 printf("Retrieving printer security for %s...", cli1->desthost);
3355 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3356 hnd1,
3359 &info1);
3360 if ( !W_ERROR_IS_OK(werror) ) {
3361 printf("failed (%s)\n", win_errstr(werror));
3362 result = false;
3363 goto done;
3365 printf("ok\n");
3367 printf("Retrieving printer security for %s...", cli2->desthost);
3368 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3369 hnd2,
3372 &info2);
3373 if ( !W_ERROR_IS_OK(werror) ) {
3374 printf("failed (%s)\n", win_errstr(werror));
3375 result = false;
3376 goto done;
3378 printf("ok\n");
3381 printf("++ ");
3383 sd1 = info1.info3.secdesc;
3384 sd2 = info2.info3.secdesc;
3386 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3387 printf("NULL secdesc!\n");
3388 result = false;
3389 goto done;
3392 if (!security_descriptor_equal( sd1, sd2 ) ) {
3393 printf("Security Descriptors *not* equal!\n");
3394 result = false;
3395 goto done;
3398 printf("Security descriptors match\n");
3400 done:
3401 talloc_destroy(mem_ctx);
3402 return result;
3406 /****************************************************************************
3407 ****************************************************************************/
3409 extern struct user_auth_info *rpcclient_auth_info;
3411 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3412 TALLOC_CTX *mem_ctx, int argc,
3413 const char **argv)
3415 const char *printername;
3416 char *printername_path = NULL;
3417 struct cli_state *cli_server2 = NULL;
3418 struct rpc_pipe_client *cli2 = NULL;
3419 struct policy_handle hPrinter1, hPrinter2;
3420 NTSTATUS nt_status;
3421 WERROR werror;
3423 if ( argc != 3 ) {
3424 printf("Usage: %s <printer> <server>\n", argv[0]);
3425 return WERR_OK;
3428 printername = argv[1];
3430 /* first get the connection to the remote server */
3432 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3433 NULL, 0,
3434 "IPC$", "IPC",
3435 get_cmdline_auth_info_username(rpcclient_auth_info),
3436 lp_workgroup(),
3437 get_cmdline_auth_info_password(rpcclient_auth_info),
3438 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3439 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3441 if ( !NT_STATUS_IS_OK(nt_status) )
3442 return WERR_GENERAL_FAILURE;
3444 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3445 &cli2);
3446 if (!NT_STATUS_IS_OK(nt_status)) {
3447 printf("failed to open spoolss pipe on server %s (%s)\n",
3448 argv[2], nt_errstr(nt_status));
3449 return WERR_GENERAL_FAILURE;
3452 /* now open up both printers */
3454 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3456 printf("Opening %s...", printername_path);
3458 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3459 printername_path,
3460 PRINTER_ALL_ACCESS,
3461 &hPrinter1);
3462 if ( !W_ERROR_IS_OK(werror) ) {
3463 printf("failed (%s)\n", win_errstr(werror));
3464 goto done;
3466 printf("ok\n");
3468 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3470 printf("Opening %s...", printername_path);
3471 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3472 printername_path,
3473 PRINTER_ALL_ACCESS,
3474 &hPrinter2);
3475 if ( !W_ERROR_IS_OK(werror) ) {
3476 printf("failed (%s)\n", win_errstr(werror));
3477 goto done;
3479 printf("ok\n");
3481 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3482 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3483 #if 0
3484 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3485 #endif
3488 done:
3489 /* cleanup */
3491 printf("Closing printers...");
3493 WERROR _result;
3494 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3495 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3497 printf("ok\n");
3499 /* close the second remote connection */
3501 cli_shutdown( cli_server2 );
3502 return WERR_OK;
3505 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3507 printf("print_processor_name: %s\n", r->print_processor_name);
3510 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3511 TALLOC_CTX *mem_ctx, int argc,
3512 const char **argv)
3514 WERROR werror;
3515 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3516 uint32_t num_procs, level = 1, i;
3517 union spoolss_PrintProcessorInfo *procs;
3519 /* Parse the command arguments */
3521 if (argc < 1 || argc > 4) {
3522 printf ("Usage: %s [environment] [level]\n", argv[0]);
3523 return WERR_OK;
3526 if (argc >= 2) {
3527 environment = argv[1];
3530 if (argc == 3) {
3531 level = atoi(argv[2]);
3534 /* Enumerate Print Processors */
3536 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3537 cli->srv_name_slash,
3538 environment,
3539 level,
3541 &num_procs,
3542 &procs);
3543 if (!W_ERROR_IS_OK(werror))
3544 goto done;
3546 /* Display output */
3548 for (i = 0; i < num_procs; i++) {
3549 switch (level) {
3550 case 1:
3551 display_proc_info1(&procs[i].info1);
3552 break;
3556 done:
3557 return werror;
3560 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3562 printf("name_array: %s\n", r->name_array);
3565 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3566 TALLOC_CTX *mem_ctx, int argc,
3567 const char **argv)
3569 WERROR werror;
3570 const char *print_processor_name = "winprint";
3571 uint32_t num_procs, level = 1, i;
3572 union spoolss_PrintProcDataTypesInfo *procs;
3574 /* Parse the command arguments */
3576 if (argc < 1 || argc > 4) {
3577 printf ("Usage: %s [environment] [level]\n", argv[0]);
3578 return WERR_OK;
3581 if (argc >= 2) {
3582 print_processor_name = argv[1];
3585 if (argc == 3) {
3586 level = atoi(argv[2]);
3589 /* Enumerate Print Processor Data Types */
3591 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3592 cli->srv_name_slash,
3593 print_processor_name,
3594 level,
3596 &num_procs,
3597 &procs);
3598 if (!W_ERROR_IS_OK(werror))
3599 goto done;
3601 /* Display output */
3603 for (i = 0; i < num_procs; i++) {
3604 switch (level) {
3605 case 1:
3606 display_proc_data_types_info1(&procs[i].info1);
3607 break;
3611 done:
3612 return werror;
3615 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3617 printf("monitor_name: %s\n", r->monitor_name);
3620 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3622 printf("monitor_name: %s\n", r->monitor_name);
3623 printf("environment: %s\n", r->environment);
3624 printf("dll_name: %s\n", r->dll_name);
3627 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3628 TALLOC_CTX *mem_ctx, int argc,
3629 const char **argv)
3631 WERROR werror;
3632 uint32_t count, level = 1, i;
3633 union spoolss_MonitorInfo *info;
3635 /* Parse the command arguments */
3637 if (argc > 2) {
3638 printf("Usage: %s [level]\n", argv[0]);
3639 return WERR_OK;
3642 if (argc == 2) {
3643 level = atoi(argv[1]);
3646 /* Enumerate Print Monitors */
3648 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3649 cli->srv_name_slash,
3650 level,
3652 &count,
3653 &info);
3654 if (!W_ERROR_IS_OK(werror)) {
3655 goto done;
3658 /* Display output */
3660 for (i = 0; i < count; i++) {
3661 switch (level) {
3662 case 1:
3663 display_monitor1(&info[i].info1);
3664 break;
3665 case 2:
3666 display_monitor2(&info[i].info2);
3667 break;
3671 done:
3672 return werror;
3675 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3676 TALLOC_CTX *mem_ctx, int argc,
3677 const char **argv)
3679 WERROR result;
3680 NTSTATUS status;
3681 struct policy_handle handle, gdi_handle;
3682 const char *printername;
3683 struct spoolss_DevmodeContainer devmode_ctr;
3684 struct dcerpc_binding_handle *b = cli->binding_handle;
3686 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3688 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3689 printername,
3690 SEC_FLAG_MAXIMUM_ALLOWED,
3691 &handle);
3692 if (!W_ERROR_IS_OK(result)) {
3693 return result;
3696 ZERO_STRUCT(devmode_ctr);
3698 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3699 &handle,
3700 &gdi_handle,
3701 &devmode_ctr,
3702 &result);
3703 if (!NT_STATUS_IS_OK(status)) {
3704 result = ntstatus_to_werror(status);
3705 goto done;
3707 if (!W_ERROR_IS_OK(result)) {
3708 goto done;
3711 done:
3712 if (is_valid_policy_hnd(&gdi_handle)) {
3713 WERROR _result;
3714 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3716 if (is_valid_policy_hnd(&handle)) {
3717 WERROR _result;
3718 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3721 return result;
3724 /* List of commands exported by this module */
3725 struct cmd_set spoolss_commands[] = {
3727 { "SPOOLSS" },
3729 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3730 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3731 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3732 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3733 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3734 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3735 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3736 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3737 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3738 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3739 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3740 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3741 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3742 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3743 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3744 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3745 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3746 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3747 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3748 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3749 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3750 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3751 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3752 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3753 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3754 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3755 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3756 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3757 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3758 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3759 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3760 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3761 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3762 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3763 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3764 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3766 { NULL }