HEIMDAL:kdc: correctly propagate HDB_ERR_NOT_FOUND_HERE to via tgs_parse_request...
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blob4eda9951b980214c6019a48cbadc8775fe55faf0
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 "rpc_client/cli_pipe.h"
28 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "rpc_client/cli_spoolss.h"
30 #include "rpc_client/init_spoolss.h"
31 #include "registry.h"
32 #include "registry/reg_objects.h"
33 #include "nt_printing.h"
35 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
36 { \
37 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
38 _cli->srv_name_slash, _arg); \
39 W_ERROR_HAVE_NO_MEMORY(_printername); \
42 /* The version int is used by getdrivers. Note that
43 all architecture strings that support mutliple
44 versions must be grouped together since enumdrivers
45 uses this property to prevent issuing multiple
46 enumdriver calls for the same arch */
49 static const struct print_architecture_table_node archi_table[]= {
51 {"Windows 4.0", "WIN40", 0 },
52 {"Windows NT x86", "W32X86", 2 },
53 {"Windows NT x86", "W32X86", 3 },
54 {"Windows NT R4000", "W32MIPS", 2 },
55 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
56 {"Windows NT PowerPC", "W32PPC", 2 },
57 {"Windows IA64", "IA64", 3 },
58 {"Windows x64", "x64", 3 },
59 {NULL, "", -1 }
62 /**
63 * @file
65 * rpcclient module for SPOOLSS rpc pipe.
67 * This generally just parses and checks command lines, and then calls
68 * a cli_spoolss function.
69 **/
71 /****************************************************************************
72 function to do the mapping between the long architecture name and
73 the short one.
74 ****************************************************************************/
76 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
78 int i=-1;
80 DEBUG(107,("Getting architecture dependent directory\n"));
81 do {
82 i++;
83 } while ( (archi_table[i].long_archi!=NULL ) &&
84 StrCaseCmp(long_archi, archi_table[i].long_archi) );
86 if (archi_table[i].long_archi==NULL) {
87 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
88 return NULL;
91 /* this might be client code - but shouldn't this be an fstrcpy etc? */
94 DEBUGADD(108,("index: [%d]\n", i));
95 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
96 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
98 return archi_table[i].short_archi;
101 /****************************************************************************
102 ****************************************************************************/
104 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
105 TALLOC_CTX *mem_ctx,
106 int argc, const char **argv)
108 WERROR werror;
109 struct policy_handle hnd;
110 uint32_t access_mask = PRINTER_ALL_ACCESS;
111 struct dcerpc_binding_handle *b = cli->binding_handle;
113 if (argc < 2) {
114 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
115 return WERR_OK;
118 if (argc >= 3) {
119 sscanf(argv[2], "%x", &access_mask);
122 /* Open the printer handle */
124 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
125 argv[1],
126 access_mask,
127 &hnd);
128 if (W_ERROR_IS_OK(werror)) {
129 printf("Printer %s opened successfully\n", argv[1]);
130 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
132 if (!W_ERROR_IS_OK(werror)) {
133 printf("Error closing printer handle! (%s)\n",
134 get_dos_error_msg(werror));
138 return werror;
141 /****************************************************************************
142 ****************************************************************************/
144 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
145 TALLOC_CTX *mem_ctx,
146 int argc, const char **argv)
148 WERROR werror;
149 struct policy_handle hnd;
150 uint32_t access_mask = PRINTER_ALL_ACCESS;
151 NTSTATUS status;
152 struct spoolss_DevmodeContainer devmode_ctr;
153 struct dcerpc_binding_handle *b = cli->binding_handle;
155 ZERO_STRUCT(devmode_ctr);
157 if (argc < 2) {
158 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
159 return WERR_OK;
162 if (argc >= 3) {
163 sscanf(argv[2], "%x", &access_mask);
166 /* Open the printer handle */
168 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
169 argv[1],
170 NULL,
171 devmode_ctr,
172 access_mask,
173 &hnd,
174 &werror);
175 if (!NT_STATUS_IS_OK(status)) {
176 return ntstatus_to_werror(status);
178 if (W_ERROR_IS_OK(werror)) {
179 printf("Printer %s opened successfully\n", argv[1]);
180 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
182 if (!W_ERROR_IS_OK(werror)) {
183 printf("Error closing printer handle! (%s)\n",
184 get_dos_error_msg(werror));
188 return werror;
191 /****************************************************************************
192 ****************************************************************************/
194 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
196 if (!r)
197 return;
199 printf("\tprintername:[%s]\n", r->printername);
200 printf("\tservername:[%s]\n", r->servername);
201 printf("\tcjobs:[0x%x]\n", r->cjobs);
202 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
203 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
204 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
205 r->time.day, r->time.day_of_week);
206 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
207 r->time.second, r->time.millisecond);
209 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
210 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
212 printf("\tversion:[0x%x]\n", r->version);
213 printf("\tfree_build:[0x%x]\n", r->free_build);
214 printf("\tspooling:[0x%x]\n", r->spooling);
215 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
216 printf("\tsession_counter:[0x%x]\n", r->session_counter);
217 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
218 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
219 printf("\tjob_error:[0x%x]\n", r->job_error);
220 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
221 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
222 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
223 printf("\tchange_id:[0x%x]\n", r->change_id);
224 printf("\tlast_error: %s\n", win_errstr(r->last_error));
225 printf("\tstatus:[0x%x]\n", r->status);
226 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
227 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
228 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
229 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
230 printf("\tref_ic:[0x%x]\n", r->ref_ic);
231 printf("\treserved2:[0x%x]\n", r->reserved2);
232 printf("\treserved3:[0x%x]\n", r->reserved3);
234 printf("\n");
237 /****************************************************************************
238 ****************************************************************************/
240 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
242 printf("\tflags:[0x%x]\n", r->flags);
243 printf("\tname:[%s]\n", r->name);
244 printf("\tdescription:[%s]\n", r->description);
245 printf("\tcomment:[%s]\n", r->comment);
247 printf("\n");
250 /****************************************************************************
251 ****************************************************************************/
253 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
255 printf("\tservername:[%s]\n", r->servername);
256 printf("\tprintername:[%s]\n", r->printername);
257 printf("\tsharename:[%s]\n", r->sharename);
258 printf("\tportname:[%s]\n", r->portname);
259 printf("\tdrivername:[%s]\n", r->drivername);
260 printf("\tcomment:[%s]\n", r->comment);
261 printf("\tlocation:[%s]\n", r->location);
262 printf("\tsepfile:[%s]\n", r->sepfile);
263 printf("\tprintprocessor:[%s]\n", r->printprocessor);
264 printf("\tdatatype:[%s]\n", r->datatype);
265 printf("\tparameters:[%s]\n", r->parameters);
266 printf("\tattributes:[0x%x]\n", r->attributes);
267 printf("\tpriority:[0x%x]\n", r->priority);
268 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
269 printf("\tstarttime:[0x%x]\n", r->starttime);
270 printf("\tuntiltime:[0x%x]\n", r->untiltime);
271 printf("\tstatus:[0x%x]\n", r->status);
272 printf("\tcjobs:[0x%x]\n", r->cjobs);
273 printf("\taverageppm:[0x%x]\n", r->averageppm);
275 if (r->secdesc)
276 display_sec_desc(r->secdesc);
278 printf("\n");
281 /****************************************************************************
282 ****************************************************************************/
284 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
286 display_sec_desc(r->secdesc);
288 printf("\n");
291 /****************************************************************************
292 ****************************************************************************/
294 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
296 printf("\tservername:[%s]\n", r->servername);
297 printf("\tprintername:[%s]\n", r->printername);
298 printf("\tattributes:[0x%x]\n", r->attributes);
299 printf("\n");
302 /****************************************************************************
303 ****************************************************************************/
305 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
307 printf("\tprintername:[%s]\n", r->printername);
308 printf("\tportname:[%s]\n", r->portname);
309 printf("\tattributes:[0x%x]\n", r->attributes);
310 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
311 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
312 printf("\n");
315 /****************************************************************************
316 ****************************************************************************/
318 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
320 printf("\tstatus:[0x%x]\n", r->status);
321 printf("\n");
324 /****************************************************************************
325 ****************************************************************************/
327 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
329 printf("\tguid:[%s]\n", r->guid);
330 printf("\taction:[0x%x]\n", r->action);
331 printf("\n");
334 /****************************************************************************
335 ****************************************************************************/
337 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
338 TALLOC_CTX *mem_ctx,
339 int argc, const char **argv)
341 WERROR result;
342 uint32_t level = 1;
343 union spoolss_PrinterInfo *info;
344 uint32_t i, count;
345 const char *name;
346 uint32_t flags = PRINTER_ENUM_LOCAL;
348 if (argc > 4) {
349 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
350 return WERR_OK;
353 if (argc >= 2) {
354 level = atoi(argv[1]);
357 if (argc >= 3) {
358 name = argv[2];
359 } else {
360 name = cli->srv_name_slash;
363 if (argc == 4) {
364 flags = atoi(argv[3]);
367 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
368 flags,
369 name,
370 level,
372 &count,
373 &info);
374 if (W_ERROR_IS_OK(result)) {
376 if (!count) {
377 printf ("No printers returned.\n");
378 goto done;
381 for (i = 0; i < count; i++) {
382 switch (level) {
383 case 0:
384 display_print_info0(&info[i].info0);
385 break;
386 case 1:
387 display_print_info1(&info[i].info1);
388 break;
389 case 2:
390 display_print_info2(&info[i].info2);
391 break;
392 case 3:
393 display_print_info3(&info[i].info3);
394 break;
395 case 4:
396 display_print_info4(&info[i].info4);
397 break;
398 case 5:
399 display_print_info5(&info[i].info5);
400 break;
401 case 6:
402 display_print_info6(&info[i].info6);
403 break;
404 default:
405 printf("unknown info level %d\n", level);
406 goto done;
410 done:
412 return result;
415 /****************************************************************************
416 ****************************************************************************/
418 static void display_port_info_1(struct spoolss_PortInfo1 *r)
420 printf("\tPort Name:\t[%s]\n", r->port_name);
423 /****************************************************************************
424 ****************************************************************************/
426 static void display_port_info_2(struct spoolss_PortInfo2 *r)
428 printf("\tPort Name:\t[%s]\n", r->port_name);
429 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
430 printf("\tDescription:\t[%s]\n", r->description);
431 printf("\tPort Type:\t" );
432 if (r->port_type) {
433 int comma = 0; /* hack */
434 printf( "[" );
435 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
436 printf( "Read" );
437 comma = 1;
439 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
440 printf( "%sWrite", comma ? ", " : "" );
441 comma = 1;
443 /* These two have slightly different interpretations
444 on 95/98/ME but I'm disregarding that for now */
445 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
446 printf( "%sRedirected", comma ? ", " : "" );
447 comma = 1;
449 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
450 printf( "%sNet-Attached", comma ? ", " : "" );
452 printf( "]\n" );
453 } else {
454 printf( "[Unset]\n" );
456 printf("\tReserved:\t[%d]\n", r->reserved);
457 printf("\n");
460 /****************************************************************************
461 ****************************************************************************/
463 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
464 TALLOC_CTX *mem_ctx, int argc,
465 const char **argv)
467 WERROR result;
468 uint32_t level = 1;
469 uint32_t count;
470 union spoolss_PortInfo *info;
472 if (argc > 2) {
473 printf("Usage: %s [level]\n", argv[0]);
474 return WERR_OK;
477 if (argc == 2) {
478 level = atoi(argv[1]);
481 /* Enumerate ports */
483 result = rpccli_spoolss_enumports(cli, mem_ctx,
484 cli->srv_name_slash,
485 level,
487 &count,
488 &info);
489 if (W_ERROR_IS_OK(result)) {
490 int i;
492 for (i = 0; i < count; i++) {
493 switch (level) {
494 case 1:
495 display_port_info_1(&info[i].info1);
496 break;
497 case 2:
498 display_port_info_2(&info[i].info2);
499 break;
500 default:
501 printf("unknown info level %d\n", level);
502 break;
507 return result;
510 /****************************************************************************
511 ****************************************************************************/
513 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
514 TALLOC_CTX *mem_ctx,
515 int argc, const char **argv)
517 struct policy_handle pol;
518 WERROR result;
519 NTSTATUS status;
520 uint32_t info_level = 2;
521 union spoolss_PrinterInfo info;
522 struct spoolss_SetPrinterInfoCtr info_ctr;
523 struct spoolss_SetPrinterInfo2 info2;
524 const char *printername, *comment = NULL;
525 struct spoolss_DevmodeContainer devmode_ctr;
526 struct sec_desc_buf secdesc_ctr;
527 struct dcerpc_binding_handle *b = cli->binding_handle;
529 if (argc == 1 || argc > 3) {
530 printf("Usage: %s printername comment\n", argv[0]);
532 return WERR_OK;
535 /* Open a printer handle */
536 if (argc == 3) {
537 comment = argv[2];
540 ZERO_STRUCT(devmode_ctr);
541 ZERO_STRUCT(secdesc_ctr);
543 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
545 /* get a printer handle */
546 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
547 printername,
548 PRINTER_ALL_ACCESS,
549 &pol);
550 if (!W_ERROR_IS_OK(result))
551 goto done;
553 /* Get printer info */
554 result = rpccli_spoolss_getprinter(cli, mem_ctx,
555 &pol,
556 info_level,
558 &info);
559 if (!W_ERROR_IS_OK(result))
560 goto done;
563 /* Modify the comment. */
564 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
565 info2.comment = comment;
567 info_ctr.level = 2;
568 info_ctr.info.info2 = &info2;
570 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
571 &pol,
572 &info_ctr,
573 &devmode_ctr,
574 &secdesc_ctr,
575 0, /* command */
576 &result);
577 if (!NT_STATUS_IS_OK(status)) {
578 result = ntstatus_to_werror(status);
579 goto done;
581 if (W_ERROR_IS_OK(result))
582 printf("Success in setting comment.\n");
584 done:
585 if (is_valid_policy_hnd(&pol)) {
586 WERROR _result;
587 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
590 return result;
593 /****************************************************************************
594 ****************************************************************************/
596 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
597 TALLOC_CTX *mem_ctx,
598 int argc, const char **argv)
600 struct policy_handle pol;
601 WERROR result;
602 NTSTATUS status;
603 uint32_t info_level = 2;
604 union spoolss_PrinterInfo info;
605 const char *printername,
606 *new_printername = NULL;
607 struct spoolss_SetPrinterInfoCtr info_ctr;
608 struct spoolss_SetPrinterInfo2 info2;
609 struct spoolss_DevmodeContainer devmode_ctr;
610 struct sec_desc_buf secdesc_ctr;
611 struct dcerpc_binding_handle *b = cli->binding_handle;
613 ZERO_STRUCT(devmode_ctr);
614 ZERO_STRUCT(secdesc_ctr);
616 if (argc == 1 || argc > 3) {
617 printf("Usage: %s printername new_printername\n", argv[0]);
619 return WERR_OK;
622 /* Open a printer handle */
623 if (argc == 3) {
624 new_printername = argv[2];
627 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
629 /* get a printer handle */
630 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
631 printername,
632 PRINTER_ALL_ACCESS,
633 &pol);
634 if (!W_ERROR_IS_OK(result))
635 goto done;
637 /* Get printer info */
638 result = rpccli_spoolss_getprinter(cli, mem_ctx,
639 &pol,
640 info_level,
642 &info);
643 if (!W_ERROR_IS_OK(result))
644 goto done;
646 /* Modify the printername. */
647 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
648 info2.printername = new_printername;
650 info_ctr.level = 2;
651 info_ctr.info.info2 = &info2;
653 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
654 &pol,
655 &info_ctr,
656 &devmode_ctr,
657 &secdesc_ctr,
658 0, /* command */
659 &result);
660 if (!NT_STATUS_IS_OK(status)) {
661 result = ntstatus_to_werror(status);
662 goto done;
664 if (W_ERROR_IS_OK(result))
665 printf("Success in setting printername.\n");
667 done:
668 if (is_valid_policy_hnd(&pol)) {
669 WERROR _result;
670 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
673 return result;
676 /****************************************************************************
677 ****************************************************************************/
679 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
680 TALLOC_CTX *mem_ctx,
681 int argc, const char **argv)
683 struct policy_handle pol;
684 WERROR result;
685 uint32_t level = 1;
686 const char *printername;
687 union spoolss_PrinterInfo info;
688 struct dcerpc_binding_handle *b = cli->binding_handle;
690 if (argc == 1 || argc > 3) {
691 printf("Usage: %s <printername> [level]\n", argv[0]);
692 return WERR_OK;
695 /* Open a printer handle */
696 if (argc == 3) {
697 level = atoi(argv[2]);
700 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
702 /* get a printer handle */
704 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
705 printername,
706 SEC_FLAG_MAXIMUM_ALLOWED,
707 &pol);
708 if (!W_ERROR_IS_OK(result)) {
709 goto done;
712 /* Get printer info */
714 result = rpccli_spoolss_getprinter(cli, mem_ctx,
715 &pol,
716 level,
718 &info);
719 if (!W_ERROR_IS_OK(result)) {
720 goto done;
723 /* Display printer info */
724 switch (level) {
725 case 0:
726 display_print_info0(&info.info0);
727 break;
728 case 1:
729 display_print_info1(&info.info1);
730 break;
731 case 2:
732 display_print_info2(&info.info2);
733 break;
734 case 3:
735 display_print_info3(&info.info3);
736 break;
737 case 4:
738 display_print_info4(&info.info4);
739 break;
740 case 5:
741 display_print_info5(&info.info5);
742 break;
743 case 6:
744 display_print_info6(&info.info6);
745 break;
746 case 7:
747 display_print_info7(&info.info7);
748 break;
749 default:
750 printf("unknown info level %d\n", level);
751 break;
753 done:
754 if (is_valid_policy_hnd(&pol)) {
755 WERROR _result;
756 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
759 return result;
762 /****************************************************************************
763 ****************************************************************************/
765 static void display_reg_value(struct regval_blob *value)
767 const char *text = NULL;
768 DATA_BLOB blob;
770 switch(regval_type(value)) {
771 case REG_DWORD:
772 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
773 *((uint32_t *) regval_data_p(value)));
774 break;
775 case REG_SZ:
776 blob = data_blob_const(regval_data_p(value), regval_size(value));
777 pull_reg_sz(talloc_tos(), &blob, &text);
778 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
779 break;
780 case REG_BINARY: {
781 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
782 size_t i, len;
783 printf("%s: REG_BINARY:", regval_name(value));
784 len = strlen(hex);
785 for (i=0; i<len; i++) {
786 if (hex[i] == '\0') {
787 break;
789 if (i%40 == 0) {
790 putchar('\n');
792 putchar(hex[i]);
794 TALLOC_FREE(hex);
795 putchar('\n');
796 break;
798 case REG_MULTI_SZ: {
799 uint32_t i;
800 const char **values;
801 blob = data_blob_const(regval_data_p(value), regval_size(value));
803 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
804 d_printf("pull_reg_multi_sz failed\n");
805 break;
808 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
809 for (i=0; values[i] != NULL; i++) {
810 d_printf("%s\n", values[i]);
812 TALLOC_FREE(values);
813 break;
815 default:
816 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
821 /****************************************************************************
822 ****************************************************************************/
824 static void display_printer_data(const char *v,
825 enum winreg_Type type,
826 uint8_t *data,
827 uint32_t length)
829 int i;
830 union spoolss_PrinterData r;
831 DATA_BLOB blob = data_blob_const(data, length);
832 WERROR result;
834 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
835 if (!W_ERROR_IS_OK(result)) {
836 return;
839 switch (type) {
840 case REG_DWORD:
841 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
842 break;
843 case REG_SZ:
844 printf("%s: REG_SZ: %s\n", v, r.string);
845 break;
846 case REG_BINARY: {
847 char *hex = hex_encode_talloc(NULL,
848 r.binary.data, r.binary.length);
849 size_t len;
850 printf("%s: REG_BINARY:", v);
851 len = strlen(hex);
852 for (i=0; i<len; i++) {
853 if (hex[i] == '\0') {
854 break;
856 if (i%40 == 0) {
857 putchar('\n');
859 putchar(hex[i]);
861 TALLOC_FREE(hex);
862 putchar('\n');
863 break;
865 case REG_MULTI_SZ:
866 printf("%s: REG_MULTI_SZ: ", v);
867 for (i=0; r.string_array[i] != NULL; i++) {
868 printf("%s ", r.string_array[i]);
870 printf("\n");
871 break;
872 default:
873 printf("%s: unknown type 0x%02x:\n", v, type);
874 break;
878 /****************************************************************************
879 ****************************************************************************/
881 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
882 TALLOC_CTX *mem_ctx,
883 int argc, const char **argv)
885 struct policy_handle pol;
886 WERROR result;
887 fstring printername;
888 const char *valuename;
889 enum winreg_Type type;
890 uint8_t *data;
891 uint32_t needed;
892 struct dcerpc_binding_handle *b = cli->binding_handle;
894 if (argc != 3) {
895 printf("Usage: %s <printername> <valuename>\n", argv[0]);
896 printf("<printername> of . queries print server\n");
897 return WERR_OK;
899 valuename = argv[2];
901 /* Open a printer handle */
903 if (strncmp(argv[1], ".", sizeof(".")) == 0)
904 fstrcpy(printername, cli->srv_name_slash);
905 else
906 slprintf(printername, sizeof(printername)-1, "%s\\%s",
907 cli->srv_name_slash, argv[1]);
909 /* get a printer handle */
911 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
912 printername,
913 SEC_FLAG_MAXIMUM_ALLOWED,
914 &pol);
915 if (!W_ERROR_IS_OK(result))
916 goto done;
918 /* Get printer info */
920 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
921 &pol,
922 valuename,
924 &type,
925 &needed,
926 &data);
927 if (!W_ERROR_IS_OK(result))
928 goto done;
930 /* Display printer data */
932 display_printer_data(valuename, type, data, needed);
934 done:
935 if (is_valid_policy_hnd(&pol)) {
936 WERROR _result;
937 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
940 return result;
943 /****************************************************************************
944 ****************************************************************************/
946 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
947 TALLOC_CTX *mem_ctx,
948 int argc, const char **argv)
950 struct policy_handle pol;
951 WERROR result;
952 NTSTATUS status;
953 fstring printername;
954 const char *valuename, *keyname;
956 enum winreg_Type type;
957 uint8_t *data = NULL;
958 uint32_t offered = 0;
959 uint32_t needed;
960 struct dcerpc_binding_handle *b = cli->binding_handle;
962 if (argc != 4) {
963 printf("Usage: %s <printername> <keyname> <valuename>\n",
964 argv[0]);
965 printf("<printername> of . queries print server\n");
966 return WERR_OK;
968 valuename = argv[3];
969 keyname = argv[2];
971 /* Open a printer handle */
973 if (strncmp(argv[1], ".", sizeof(".")) == 0)
974 fstrcpy(printername, cli->srv_name_slash);
975 else
976 slprintf(printername, sizeof(printername)-1, "%s\\%s",
977 cli->srv_name_slash, argv[1]);
979 /* get a printer handle */
981 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
982 printername,
983 SEC_FLAG_MAXIMUM_ALLOWED,
984 &pol);
985 if (!W_ERROR_IS_OK(result))
986 goto done;
988 /* Get printer info */
990 data = talloc_zero_array(mem_ctx, uint8_t, offered);
991 if (!data) {
992 goto done;
995 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
996 &pol,
997 keyname,
998 valuename,
999 &type,
1000 data,
1001 offered,
1002 &needed,
1003 &result);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 result = ntstatus_to_werror(status);
1006 goto done;
1008 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1009 offered = needed;
1010 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1011 if (!data) {
1012 goto done;
1014 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1015 &pol,
1016 keyname,
1017 valuename,
1018 &type,
1019 data,
1020 offered,
1021 &needed,
1022 &result);
1025 if (!NT_STATUS_IS_OK(status)) {
1026 result = ntstatus_to_werror(status);
1027 goto done;
1030 if (!W_ERROR_IS_OK(result))
1031 goto done;
1033 /* Display printer data */
1035 display_printer_data(valuename, type, data, needed);
1038 done:
1039 if (is_valid_policy_hnd(&pol)) {
1040 WERROR _result;
1041 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1044 return result;
1047 /****************************************************************************
1048 ****************************************************************************/
1050 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1052 if (!r) {
1053 return;
1056 printf("Printer Driver Info 1:\n");
1057 printf("\tDriver Name: [%s]\n", r->driver_name);
1058 printf("\n");
1061 /****************************************************************************
1062 ****************************************************************************/
1064 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1066 if (!r) {
1067 return;
1070 printf("Printer Driver Info 2:\n");
1071 printf("\tVersion: [%x]\n", r->version);
1072 printf("\tDriver Name: [%s]\n", r->driver_name);
1073 printf("\tArchitecture: [%s]\n", r->architecture);
1074 printf("\tDriver Path: [%s]\n", r->driver_path);
1075 printf("\tDatafile: [%s]\n", r->data_file);
1076 printf("\tConfigfile: [%s]\n", r->config_file);
1077 printf("\n");
1080 /****************************************************************************
1081 ****************************************************************************/
1083 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1085 int i;
1087 if (!r) {
1088 return;
1091 printf("Printer Driver Info 3:\n");
1092 printf("\tVersion: [%x]\n", r->version);
1093 printf("\tDriver Name: [%s]\n", r->driver_name);
1094 printf("\tArchitecture: [%s]\n", r->architecture);
1095 printf("\tDriver Path: [%s]\n", r->driver_path);
1096 printf("\tDatafile: [%s]\n", r->data_file);
1097 printf("\tConfigfile: [%s]\n", r->config_file);
1098 printf("\tHelpfile: [%s]\n", r->help_file);
1100 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1101 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1104 printf("\tMonitorname: [%s]\n", r->monitor_name);
1105 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1106 printf("\n");
1109 /****************************************************************************
1110 ****************************************************************************/
1112 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1114 int i;
1116 if (!r) {
1117 return;
1120 printf("Printer Driver Info 4:\n");
1121 printf("\tVersion: [%x]\n", r->version);
1122 printf("\tDriver Name: [%s]\n", r->driver_name);
1123 printf("\tArchitecture: [%s]\n", r->architecture);
1124 printf("\tDriver Path: [%s]\n", r->driver_path);
1125 printf("\tDatafile: [%s]\n", r->data_file);
1126 printf("\tConfigfile: [%s]\n", r->config_file);
1127 printf("\tHelpfile: [%s]\n", r->help_file);
1129 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1130 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1133 printf("\tMonitorname: [%s]\n", r->monitor_name);
1134 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1136 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1137 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1139 printf("\n");
1142 /****************************************************************************
1143 ****************************************************************************/
1145 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1147 if (!r) {
1148 return;
1151 printf("Printer Driver Info 5:\n");
1152 printf("\tVersion: [%x]\n", r->version);
1153 printf("\tDriver Name: [%s]\n", r->driver_name);
1154 printf("\tArchitecture: [%s]\n", r->architecture);
1155 printf("\tDriver Path: [%s]\n", r->driver_path);
1156 printf("\tDatafile: [%s]\n", r->data_file);
1157 printf("\tConfigfile: [%s]\n", r->config_file);
1158 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1159 printf("\tConfig Version: [0x%x]\n", r->config_version);
1160 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1161 printf("\n");
1164 /****************************************************************************
1165 ****************************************************************************/
1167 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1169 int i;
1171 if (!r) {
1172 return;
1175 printf("Printer Driver Info 6:\n");
1176 printf("\tVersion: [%x]\n", r->version);
1177 printf("\tDriver Name: [%s]\n", r->driver_name);
1178 printf("\tArchitecture: [%s]\n", r->architecture);
1179 printf("\tDriver Path: [%s]\n", r->driver_path);
1180 printf("\tDatafile: [%s]\n", r->data_file);
1181 printf("\tConfigfile: [%s]\n", r->config_file);
1182 printf("\tHelpfile: [%s]\n", r->help_file);
1184 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1185 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1188 printf("\tMonitorname: [%s]\n", r->monitor_name);
1189 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1191 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1192 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1195 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1196 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1197 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1198 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1199 printf("\tHardware ID: [%s]\n", r->hardware_id);
1200 printf("\tProvider: [%s]\n", r->provider);
1202 printf("\n");
1205 /****************************************************************************
1206 ****************************************************************************/
1208 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1210 int i;
1212 if (!r) {
1213 return;
1216 printf("Printer Driver Info 8:\n");
1217 printf("\tVersion: [%x]\n", r->version);
1218 printf("\tDriver Name: [%s]\n", r->driver_name);
1219 printf("\tArchitecture: [%s]\n", r->architecture);
1220 printf("\tDriver Path: [%s]\n", r->driver_path);
1221 printf("\tDatafile: [%s]\n", r->data_file);
1222 printf("\tConfigfile: [%s]\n", r->config_file);
1223 printf("\tHelpfile: [%s]\n", r->help_file);
1224 printf("\tMonitorname: [%s]\n", r->monitor_name);
1225 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1227 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1228 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1231 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1232 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1235 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1236 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1237 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1238 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1239 printf("\tHardware ID: [%s]\n", r->hardware_id);
1240 printf("\tProvider: [%s]\n", r->provider);
1241 printf("\tPrint Processor: [%s]\n", r->print_processor);
1242 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1243 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1244 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1246 printf("\tInf Path: [%s]\n", r->inf_path);
1247 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1248 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1249 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1251 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1252 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1253 (long long unsigned int)r->min_inbox_driver_ver_version);
1255 printf("\n");
1258 /****************************************************************************
1259 ****************************************************************************/
1261 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1262 TALLOC_CTX *mem_ctx,
1263 int argc, const char **argv)
1265 struct policy_handle pol;
1266 WERROR werror;
1267 uint32_t level = 3;
1268 const char *printername;
1269 uint32_t i;
1270 bool success = false;
1271 union spoolss_DriverInfo info;
1272 uint32_t server_major_version;
1273 uint32_t server_minor_version;
1274 struct dcerpc_binding_handle *b = cli->binding_handle;
1276 if ((argc == 1) || (argc > 3)) {
1277 printf("Usage: %s <printername> [level]\n", argv[0]);
1278 return WERR_OK;
1281 /* get the arguments need to open the printer handle */
1283 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1285 if (argc == 3) {
1286 level = atoi(argv[2]);
1289 /* Open a printer handle */
1291 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1292 printername,
1293 PRINTER_ACCESS_USE,
1294 &pol);
1295 if (!W_ERROR_IS_OK(werror)) {
1296 printf("Error opening printer handle for %s!\n", printername);
1297 return werror;
1300 /* loop through and print driver info level for each architecture */
1302 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1304 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1305 &pol,
1306 archi_table[i].long_archi,
1307 level,
1308 0, /* offered */
1309 archi_table[i].version,
1311 &info,
1312 &server_major_version,
1313 &server_minor_version);
1314 if (!W_ERROR_IS_OK(werror)) {
1315 continue;
1318 /* need at least one success */
1320 success = true;
1322 printf("\n[%s]\n", archi_table[i].long_archi);
1324 switch (level) {
1325 case 1:
1326 display_print_driver1(&info.info1);
1327 break;
1328 case 2:
1329 display_print_driver2(&info.info2);
1330 break;
1331 case 3:
1332 display_print_driver3(&info.info3);
1333 break;
1334 case 4:
1335 display_print_driver4(&info.info4);
1336 break;
1337 case 5:
1338 display_print_driver5(&info.info5);
1339 break;
1340 case 6:
1341 display_print_driver6(&info.info6);
1342 break;
1343 case 8:
1344 display_print_driver8(&info.info8);
1345 break;
1346 default:
1347 printf("unknown info level %d\n", level);
1348 break;
1352 /* Cleanup */
1354 if (is_valid_policy_hnd(&pol)) {
1355 WERROR _result;
1356 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1359 if (success) {
1360 werror = WERR_OK;
1363 return werror;
1366 /****************************************************************************
1367 ****************************************************************************/
1369 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1370 TALLOC_CTX *mem_ctx,
1371 const char *architecture,
1372 uint32_t level)
1374 WERROR werror;
1375 uint32_t count = 0;
1376 union spoolss_DriverInfo *info = NULL;
1377 uint32_t j;
1379 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1380 cli->srv_name_slash,
1381 architecture,
1382 level,
1384 &count,
1385 &info);
1387 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1388 printf("Server does not support environment [%s]\n",
1389 architecture);
1390 return WERR_OK;
1393 if (count == 0) {
1394 return WERR_OK;
1397 if (!W_ERROR_IS_OK(werror)) {
1398 printf("Error getting driver for environment [%s] - %s\n",
1399 architecture, win_errstr(werror));
1400 return werror;
1403 printf("\n[%s]\n", architecture);
1405 switch (level) {
1406 case 1:
1407 for (j=0; j < count; j++) {
1408 display_print_driver1(&info[j].info1);
1410 break;
1411 case 2:
1412 for (j=0; j < count; j++) {
1413 display_print_driver2(&info[j].info2);
1415 break;
1416 case 3:
1417 for (j=0; j < count; j++) {
1418 display_print_driver3(&info[j].info3);
1420 break;
1421 case 4:
1422 for (j=0; j < count; j++) {
1423 display_print_driver4(&info[j].info4);
1425 break;
1426 case 5:
1427 for (j=0; j < count; j++) {
1428 display_print_driver5(&info[j].info5);
1430 break;
1431 case 6:
1432 for (j=0; j < count; j++) {
1433 display_print_driver6(&info[j].info6);
1435 break;
1436 case 8:
1437 for (j=0; j < count; j++) {
1438 display_print_driver8(&info[j].info8);
1440 break;
1441 default:
1442 printf("unknown info level %d\n", level);
1443 return WERR_UNKNOWN_LEVEL;
1446 return werror;
1449 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1450 TALLOC_CTX *mem_ctx,
1451 int argc, const char **argv)
1453 WERROR werror = WERR_OK;
1454 uint32_t level = 1;
1455 uint32_t i;
1456 const char *architecture = NULL;
1458 if (argc > 3) {
1459 printf("Usage: enumdrivers [level] [architecture]\n");
1460 return WERR_OK;
1463 if (argc >= 2) {
1464 level = atoi(argv[1]);
1467 if (argc == 3) {
1468 architecture = argv[2];
1471 if (architecture) {
1472 return enum_driver_by_architecture(cli, mem_ctx,
1473 architecture,
1474 level);
1477 /* loop through and print driver info level for each architecture */
1478 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1479 /* check to see if we already asked for this architecture string */
1481 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1482 continue;
1485 werror = enum_driver_by_architecture(cli, mem_ctx,
1486 archi_table[i].long_archi,
1487 level);
1488 if (!W_ERROR_IS_OK(werror)) {
1489 break;
1493 return werror;
1496 /****************************************************************************
1497 ****************************************************************************/
1499 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1501 printf("\tDirectory Name:[%s]\n", r->directory_name);
1504 /****************************************************************************
1505 ****************************************************************************/
1507 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1508 TALLOC_CTX *mem_ctx,
1509 int argc, const char **argv)
1511 WERROR result;
1512 NTSTATUS status;
1513 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1514 DATA_BLOB buffer;
1515 uint32_t offered;
1516 union spoolss_DriverDirectoryInfo info;
1517 uint32_t needed;
1518 struct dcerpc_binding_handle *b = cli->binding_handle;
1520 if (argc > 2) {
1521 printf("Usage: %s [environment]\n", argv[0]);
1522 return WERR_OK;
1525 /* Get the arguments need to open the printer handle */
1527 if (argc == 2) {
1528 env = argv[1];
1531 /* Get the directory. Only use Info level 1 */
1533 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1534 cli->srv_name_slash,
1535 env,
1537 NULL, /* buffer */
1538 0, /* offered */
1539 NULL, /* info */
1540 &needed,
1541 &result);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 return ntstatus_to_werror(status);
1545 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1546 offered = needed;
1547 buffer = data_blob_talloc_zero(mem_ctx, needed);
1549 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1550 cli->srv_name_slash,
1551 env,
1553 &buffer,
1554 offered,
1555 &info,
1556 &needed,
1557 &result);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 return ntstatus_to_werror(status);
1563 if (W_ERROR_IS_OK(result)) {
1564 display_printdriverdir_1(&info.info1);
1567 return result;
1570 /****************************************************************************
1571 ****************************************************************************/
1573 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1574 struct spoolss_AddDriverInfo3 *info,
1575 const char *arch)
1578 int i;
1580 for (i=0; archi_table[i].long_archi != NULL; i++)
1582 if (strcmp(arch, archi_table[i].short_archi) == 0)
1584 info->version = archi_table[i].version;
1585 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1586 break;
1590 if (archi_table[i].long_archi == NULL)
1592 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1595 return;
1599 /**************************************************************************
1600 wrapper for strtok to get the next parameter from a delimited list.
1601 Needed to handle the empty parameter string denoted by "NULL"
1602 *************************************************************************/
1604 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1605 const char *delim, const char **dest,
1606 char **saveptr)
1608 char *ptr;
1610 /* get the next token */
1611 ptr = strtok_r(str, delim, saveptr);
1613 /* a string of 'NULL' is used to represent an empty
1614 parameter because two consecutive delimiters
1615 will not return an empty string. See man strtok(3)
1616 for details */
1617 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1618 ptr = NULL;
1621 if (dest != NULL) {
1622 *dest = talloc_strdup(mem_ctx, ptr);
1625 return ptr;
1628 /********************************************************************************
1629 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1630 string in the form of
1631 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1632 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1633 <Default Data Type>:<Comma Separated list of Files>
1634 *******************************************************************************/
1636 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1637 char *args)
1639 char *str, *str2;
1640 int count = 0;
1641 char *saveptr = NULL;
1642 struct spoolss_StringArray *deps;
1643 const char **file_array = NULL;
1644 int i;
1646 /* fill in the UNISTR fields */
1647 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1648 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1649 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1650 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1651 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1652 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1653 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1655 /* <Comma Separated List of Dependent Files> */
1656 /* save the beginning of the string */
1657 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1658 str = str2;
1660 /* begin to strip out each filename */
1661 str = strtok_r(str, ",", &saveptr);
1663 /* no dependent files, we are done */
1664 if (!str) {
1665 return true;
1668 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1669 if (!deps) {
1670 return false;
1673 while (str != NULL) {
1674 add_string_to_array(deps, str, &file_array, &count);
1675 str = strtok_r(NULL, ",", &saveptr);
1678 deps->string = talloc_zero_array(deps, const char *, count + 1);
1679 if (!deps->string) {
1680 return false;
1683 for (i=0; i < count; i++) {
1684 deps->string[i] = file_array[i];
1687 r->dependent_files = deps;
1689 return true;
1692 /****************************************************************************
1693 ****************************************************************************/
1695 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1696 TALLOC_CTX *mem_ctx,
1697 int argc, const char **argv)
1699 WERROR result;
1700 NTSTATUS status;
1701 uint32_t level = 3;
1702 struct spoolss_AddDriverInfoCtr info_ctr;
1703 struct spoolss_AddDriverInfo3 info3;
1704 const char *arch;
1705 char *driver_args;
1706 struct dcerpc_binding_handle *b = cli->binding_handle;
1708 /* parse the command arguments */
1709 if (argc != 3 && argc != 4)
1711 printf ("Usage: %s <Environment> \\\n", argv[0]);
1712 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1713 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1714 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1715 printf ("\t[version]\n");
1717 return WERR_OK;
1720 /* Fill in the spoolss_AddDriverInfo3 struct */
1721 ZERO_STRUCT(info3);
1723 arch = cmd_spoolss_get_short_archi(argv[1]);
1724 if (!arch) {
1725 printf ("Error Unknown architecture [%s]\n", argv[1]);
1726 return WERR_INVALID_PARAM;
1729 set_drv_info_3_env(mem_ctx, &info3, arch);
1731 driver_args = talloc_strdup( mem_ctx, argv[2] );
1732 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1734 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1735 return WERR_INVALID_PARAM;
1738 /* if printer driver version specified, override the default version
1739 * used by the architecture. This allows installation of Windows
1740 * 2000 (version 3) printer drivers. */
1741 if (argc == 4)
1743 info3.version = atoi(argv[3]);
1747 info_ctr.level = level;
1748 info_ctr.info.info3 = &info3;
1750 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1751 cli->srv_name_slash,
1752 &info_ctr,
1753 &result);
1754 if (!NT_STATUS_IS_OK(status)) {
1755 return ntstatus_to_werror(status);
1757 if (W_ERROR_IS_OK(result)) {
1758 printf ("Printer Driver %s successfully installed.\n",
1759 info3.driver_name);
1762 return result;
1766 /****************************************************************************
1767 ****************************************************************************/
1769 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1770 TALLOC_CTX *mem_ctx,
1771 int argc, const char **argv)
1773 WERROR result;
1774 struct spoolss_SetPrinterInfoCtr info_ctr;
1775 struct spoolss_SetPrinterInfo2 info2;
1777 /* parse the command arguments */
1778 if (argc != 5)
1780 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1781 return WERR_OK;
1784 /* Fill in the DRIVER_INFO_2 struct */
1785 ZERO_STRUCT(info2);
1787 info2.printername = argv[1];
1788 info2.drivername = argv[3];
1789 info2.sharename = argv[2];
1790 info2.portname = argv[4];
1791 info2.comment = "Created by rpcclient";
1792 info2.printprocessor = "winprint";
1793 info2.datatype = "RAW";
1794 info2.devmode_ptr = 0;
1795 info2.secdesc_ptr = 0;
1796 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1797 info2.priority = 0;
1798 info2.defaultpriority = 0;
1799 info2.starttime = 0;
1800 info2.untiltime = 0;
1802 /* These three fields must not be used by AddPrinter()
1803 as defined in the MS Platform SDK documentation..
1804 --jerry
1805 info2.status = 0;
1806 info2.cjobs = 0;
1807 info2.averageppm = 0;
1810 info_ctr.level = 2;
1811 info_ctr.info.info2 = &info2;
1813 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1814 &info_ctr);
1815 if (W_ERROR_IS_OK(result))
1816 printf ("Printer %s successfully installed.\n", argv[1]);
1818 return result;
1821 /****************************************************************************
1822 ****************************************************************************/
1824 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1825 TALLOC_CTX *mem_ctx,
1826 int argc, const char **argv)
1828 struct policy_handle pol;
1829 WERROR result;
1830 NTSTATUS status;
1831 uint32_t level = 2;
1832 const char *printername;
1833 union spoolss_PrinterInfo info;
1834 struct spoolss_SetPrinterInfoCtr info_ctr;
1835 struct spoolss_SetPrinterInfo2 info2;
1836 struct spoolss_DevmodeContainer devmode_ctr;
1837 struct sec_desc_buf secdesc_ctr;
1838 struct dcerpc_binding_handle *b = cli->binding_handle;
1840 ZERO_STRUCT(devmode_ctr);
1841 ZERO_STRUCT(secdesc_ctr);
1843 /* parse the command arguments */
1844 if (argc != 3)
1846 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1847 return WERR_OK;
1850 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1852 /* Get a printer handle */
1854 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1855 printername,
1856 PRINTER_ALL_ACCESS,
1857 &pol);
1858 if (!W_ERROR_IS_OK(result))
1859 goto done;
1861 /* Get printer info */
1863 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1864 &pol,
1865 level,
1867 &info);
1868 if (!W_ERROR_IS_OK(result)) {
1869 printf ("Unable to retrieve printer information!\n");
1870 goto done;
1873 /* Set the printer driver */
1875 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1876 info2.drivername = argv[2];
1878 info_ctr.level = 2;
1879 info_ctr.info.info2 = &info2;
1881 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1882 &pol,
1883 &info_ctr,
1884 &devmode_ctr,
1885 &secdesc_ctr,
1886 0, /* command */
1887 &result);
1888 if (!NT_STATUS_IS_OK(status)) {
1889 result = ntstatus_to_werror(status);
1890 goto done;
1892 if (!W_ERROR_IS_OK(result)) {
1893 printf("SetPrinter call failed!\n");
1894 goto done;
1897 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1899 done:
1900 /* Cleanup */
1902 if (is_valid_policy_hnd(&pol)) {
1903 WERROR _result;
1904 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1907 return result;
1911 /****************************************************************************
1912 ****************************************************************************/
1914 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1915 TALLOC_CTX *mem_ctx,
1916 int argc, const char **argv)
1918 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1919 NTSTATUS status;
1920 struct dcerpc_binding_handle *b = cli->binding_handle;
1922 int i;
1923 int vers = -1;
1925 const char *arch = NULL;
1926 uint32_t delete_flags = 0;
1928 /* parse the command arguments */
1929 if (argc < 2 || argc > 4) {
1930 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1931 return WERR_OK;
1934 if (argc >= 3)
1935 arch = argv[2];
1936 if (argc == 4)
1937 vers = atoi (argv[3]);
1939 if (vers >= 0) {
1940 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1943 /* delete the driver for all architectures */
1944 for (i=0; archi_table[i].long_archi; i++) {
1946 if (arch && !strequal( archi_table[i].long_archi, arch))
1947 continue;
1949 if (vers >= 0 && archi_table[i].version != vers)
1950 continue;
1952 /* make the call to remove the driver */
1953 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1954 cli->srv_name_slash,
1955 archi_table[i].long_archi,
1956 argv[1],
1957 delete_flags,
1958 archi_table[i].version,
1959 &result);
1960 if (!NT_STATUS_IS_OK(status)) {
1961 return ntstatus_to_werror(status);
1963 if ( !W_ERROR_IS_OK(result) )
1965 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1966 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1967 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1970 else
1972 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1973 archi_table[i].long_archi, archi_table[i].version);
1974 ret = WERR_OK;
1978 return ret;
1982 /****************************************************************************
1983 ****************************************************************************/
1985 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1986 TALLOC_CTX *mem_ctx,
1987 int argc, const char **argv)
1989 WERROR result = WERR_OK;
1990 NTSTATUS status;
1991 int i;
1992 struct dcerpc_binding_handle *b = cli->binding_handle;
1994 /* parse the command arguments */
1995 if (argc != 2) {
1996 printf ("Usage: %s <driver>\n", argv[0]);
1997 return WERR_OK;
2000 /* delete the driver for all architectures */
2001 for (i=0; archi_table[i].long_archi; i++) {
2002 result = WERR_OK;
2004 /* make the call to remove the driver */
2005 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2006 cli->srv_name_slash,
2007 archi_table[i].long_archi,
2008 argv[1],
2009 &result);
2010 if (!NT_STATUS_IS_OK(status)) {
2011 result = ntstatus_to_werror(status);
2012 continue;
2014 if ( !W_ERROR_IS_OK(result) ) {
2015 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2016 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2017 argv[1], archi_table[i].long_archi,
2018 win_errstr(result));
2020 } else {
2021 printf ("Driver %s removed for arch [%s].\n", argv[1],
2022 archi_table[i].long_archi);
2026 return result;
2029 /****************************************************************************
2030 ****************************************************************************/
2032 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2033 TALLOC_CTX *mem_ctx,
2034 int argc, const char **argv)
2036 WERROR result;
2037 NTSTATUS status;
2038 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2039 DATA_BLOB buffer;
2040 uint32_t offered;
2041 union spoolss_PrintProcessorDirectoryInfo info;
2042 uint32_t needed;
2043 struct dcerpc_binding_handle *b = cli->binding_handle;
2045 /* parse the command arguments */
2046 if (argc > 2) {
2047 printf ("Usage: %s [environment]\n", argv[0]);
2048 return WERR_OK;
2051 if (argc == 2) {
2052 environment = argv[1];
2055 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2056 cli->srv_name_slash,
2057 environment,
2059 NULL, /* buffer */
2060 0, /* offered */
2061 NULL, /* info */
2062 &needed,
2063 &result);
2064 if (!NT_STATUS_IS_OK(status)) {
2065 return ntstatus_to_werror(status);
2067 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2068 offered = needed;
2069 buffer = data_blob_talloc_zero(mem_ctx, needed);
2071 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2072 cli->srv_name_slash,
2073 environment,
2075 &buffer,
2076 offered,
2077 &info,
2078 &needed,
2079 &result);
2080 if (!NT_STATUS_IS_OK(status)) {
2081 return ntstatus_to_werror(status);
2085 if (W_ERROR_IS_OK(result)) {
2086 printf("%s\n", info.info1.directory_name);
2089 return result;
2092 /****************************************************************************
2093 ****************************************************************************/
2095 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2096 int argc, const char **argv)
2098 struct policy_handle handle;
2099 WERROR werror;
2100 NTSTATUS status;
2101 const char *printername;
2102 union spoolss_AddFormInfo info;
2103 struct spoolss_AddFormInfo1 info1;
2104 struct spoolss_AddFormInfo2 info2;
2105 uint32_t level = 1;
2106 struct dcerpc_binding_handle *b = cli->binding_handle;
2108 /* Parse the command arguments */
2110 if (argc < 3 || argc > 5) {
2111 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2112 return WERR_OK;
2115 /* Get a printer handle */
2117 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2119 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2120 printername,
2121 PRINTER_ALL_ACCESS,
2122 &handle);
2123 if (!W_ERROR_IS_OK(werror))
2124 goto done;
2126 /* Dummy up some values for the form data */
2128 if (argc == 4) {
2129 level = atoi(argv[3]);
2132 switch (level) {
2133 case 1:
2134 info1.flags = SPOOLSS_FORM_USER;
2135 info1.form_name = argv[2];
2136 info1.size.width = 100;
2137 info1.size.height = 100;
2138 info1.area.left = 0;
2139 info1.area.top = 10;
2140 info1.area.right = 20;
2141 info1.area.bottom = 30;
2143 info.info1 = &info1;
2145 break;
2146 case 2:
2147 info2.flags = SPOOLSS_FORM_USER;
2148 info2.form_name = argv[2];
2149 info2.size.width = 100;
2150 info2.size.height = 100;
2151 info2.area.left = 0;
2152 info2.area.top = 10;
2153 info2.area.right = 20;
2154 info2.area.bottom = 30;
2155 info2.keyword = argv[2];
2156 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2157 info2.mui_dll = NULL;
2158 info2.ressource_id = 0;
2159 info2.display_name = argv[2];
2160 info2.lang_id = 0;
2162 info.info2 = &info2;
2164 break;
2165 default:
2166 werror = WERR_INVALID_PARAM;
2167 goto done;
2170 /* Add the form */
2173 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2174 &handle,
2175 level,
2176 info,
2177 &werror);
2178 if (!NT_STATUS_IS_OK(status)) {
2179 werror = ntstatus_to_werror(status);
2180 goto done;
2182 done:
2183 if (is_valid_policy_hnd(&handle)) {
2184 WERROR _result;
2185 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2188 return werror;
2191 /****************************************************************************
2192 ****************************************************************************/
2194 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2195 int argc, const char **argv)
2197 struct policy_handle handle;
2198 WERROR werror;
2199 NTSTATUS status;
2200 const char *printername;
2201 union spoolss_AddFormInfo info;
2202 struct spoolss_AddFormInfo1 info1;
2203 struct dcerpc_binding_handle *b = cli->binding_handle;
2205 /* Parse the command arguments */
2207 if (argc != 3) {
2208 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2209 return WERR_OK;
2212 /* Get a printer handle */
2214 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2216 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2217 printername,
2218 SEC_FLAG_MAXIMUM_ALLOWED,
2219 &handle);
2220 if (!W_ERROR_IS_OK(werror))
2221 goto done;
2223 /* Dummy up some values for the form data */
2225 info1.flags = SPOOLSS_FORM_PRINTER;
2226 info1.size.width = 100;
2227 info1.size.height = 100;
2228 info1.area.left = 0;
2229 info1.area.top = 1000;
2230 info1.area.right = 2000;
2231 info1.area.bottom = 3000;
2232 info1.form_name = argv[2];
2234 info.info1 = &info1;
2236 /* Set the form */
2238 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2239 &handle,
2240 argv[2],
2242 info,
2243 &werror);
2244 if (!NT_STATUS_IS_OK(status)) {
2245 werror = ntstatus_to_werror(status);
2246 goto done;
2248 done:
2249 if (is_valid_policy_hnd(&handle)) {
2250 WERROR _result;
2251 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2254 return werror;
2257 /****************************************************************************
2258 ****************************************************************************/
2260 static const char *get_form_flag(int form_flag)
2262 switch (form_flag) {
2263 case SPOOLSS_FORM_USER:
2264 return "FORM_USER";
2265 case SPOOLSS_FORM_BUILTIN:
2266 return "FORM_BUILTIN";
2267 case SPOOLSS_FORM_PRINTER:
2268 return "FORM_PRINTER";
2269 default:
2270 return "unknown";
2274 /****************************************************************************
2275 ****************************************************************************/
2277 static void display_form_info1(struct spoolss_FormInfo1 *r)
2279 printf("%s\n" \
2280 "\tflag: %s (%d)\n" \
2281 "\twidth: %d, length: %d\n" \
2282 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2283 r->form_name, get_form_flag(r->flags), r->flags,
2284 r->size.width, r->size.height,
2285 r->area.left, r->area.right,
2286 r->area.top, r->area.bottom);
2289 /****************************************************************************
2290 ****************************************************************************/
2292 static void display_form_info2(struct spoolss_FormInfo2 *r)
2294 printf("%s\n" \
2295 "\tflag: %s (%d)\n" \
2296 "\twidth: %d, length: %d\n" \
2297 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2298 r->form_name, get_form_flag(r->flags), r->flags,
2299 r->size.width, r->size.height,
2300 r->area.left, r->area.right,
2301 r->area.top, r->area.bottom);
2302 printf("\tkeyword: %s\n", r->keyword);
2303 printf("\tstring_type: 0x%08x\n", r->string_type);
2304 printf("\tmui_dll: %s\n", r->mui_dll);
2305 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2306 printf("\tdisplay_name: %s\n", r->display_name);
2307 printf("\tlang_id: %d\n", r->lang_id);
2308 printf("\n");
2311 /****************************************************************************
2312 ****************************************************************************/
2314 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2315 int argc, const char **argv)
2317 struct policy_handle handle;
2318 WERROR werror;
2319 NTSTATUS status;
2320 const char *printername;
2321 DATA_BLOB buffer;
2322 uint32_t offered = 0;
2323 union spoolss_FormInfo info;
2324 uint32_t needed;
2325 uint32_t level = 1;
2326 struct dcerpc_binding_handle *b = cli->binding_handle;
2328 /* Parse the command arguments */
2330 if (argc < 3 || argc > 5) {
2331 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2332 return WERR_OK;
2335 /* Get a printer handle */
2337 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2339 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2340 printername,
2341 SEC_FLAG_MAXIMUM_ALLOWED,
2342 &handle);
2343 if (!W_ERROR_IS_OK(werror))
2344 goto done;
2346 if (argc == 4) {
2347 level = atoi(argv[3]);
2350 /* Get the form */
2352 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2353 &handle,
2354 argv[2],
2355 level,
2356 NULL,
2357 offered,
2358 &info,
2359 &needed,
2360 &werror);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 werror = ntstatus_to_werror(status);
2363 goto done;
2365 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2366 buffer = data_blob_talloc_zero(mem_ctx, needed);
2367 offered = needed;
2368 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2369 &handle,
2370 argv[2],
2371 level,
2372 &buffer,
2373 offered,
2374 &info,
2375 &needed,
2376 &werror);
2377 if (!NT_STATUS_IS_OK(status)) {
2378 werror = ntstatus_to_werror(status);
2379 goto done;
2383 if (!W_ERROR_IS_OK(werror)) {
2384 goto done;
2387 switch (level) {
2388 case 1:
2389 display_form_info1(&info.info1);
2390 break;
2391 case 2:
2392 display_form_info2(&info.info2);
2393 break;
2396 done:
2397 if (is_valid_policy_hnd(&handle)) {
2398 WERROR _result;
2399 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2402 return werror;
2405 /****************************************************************************
2406 ****************************************************************************/
2408 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2409 TALLOC_CTX *mem_ctx, int argc,
2410 const char **argv)
2412 struct policy_handle handle;
2413 WERROR werror;
2414 NTSTATUS status;
2415 const char *printername;
2416 struct dcerpc_binding_handle *b = cli->binding_handle;
2418 /* Parse the command arguments */
2420 if (argc != 3) {
2421 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2422 return WERR_OK;
2425 /* Get a printer handle */
2427 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2429 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2430 printername,
2431 SEC_FLAG_MAXIMUM_ALLOWED,
2432 &handle);
2433 if (!W_ERROR_IS_OK(werror))
2434 goto done;
2436 /* Delete the form */
2438 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2439 &handle,
2440 argv[2],
2441 &werror);
2442 if (!NT_STATUS_IS_OK(status)) {
2443 werror = ntstatus_to_werror(status);
2444 goto done;
2447 done:
2448 if (is_valid_policy_hnd(&handle)) {
2449 WERROR _result;
2450 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2453 return werror;
2456 /****************************************************************************
2457 ****************************************************************************/
2459 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2460 TALLOC_CTX *mem_ctx, int argc,
2461 const char **argv)
2463 struct policy_handle handle;
2464 WERROR werror;
2465 const char *printername;
2466 uint32_t num_forms, level = 1, i;
2467 union spoolss_FormInfo *forms;
2468 struct dcerpc_binding_handle *b = cli->binding_handle;
2470 /* Parse the command arguments */
2472 if (argc < 2 || argc > 4) {
2473 printf ("Usage: %s <printer> [level]\n", argv[0]);
2474 return WERR_OK;
2477 /* Get a printer handle */
2479 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2481 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2482 printername,
2483 SEC_FLAG_MAXIMUM_ALLOWED,
2484 &handle);
2485 if (!W_ERROR_IS_OK(werror))
2486 goto done;
2488 if (argc == 3) {
2489 level = atoi(argv[2]);
2492 /* Enumerate forms */
2494 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2495 &handle,
2496 level,
2498 &num_forms,
2499 &forms);
2501 if (!W_ERROR_IS_OK(werror))
2502 goto done;
2504 /* Display output */
2506 for (i = 0; i < num_forms; i++) {
2507 switch (level) {
2508 case 1:
2509 display_form_info1(&forms[i].info1);
2510 break;
2511 case 2:
2512 display_form_info2(&forms[i].info2);
2513 break;
2517 done:
2518 if (is_valid_policy_hnd(&handle)) {
2519 WERROR _result;
2520 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2523 return werror;
2526 /****************************************************************************
2527 ****************************************************************************/
2529 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2530 TALLOC_CTX *mem_ctx,
2531 int argc, const char **argv)
2533 WERROR result;
2534 NTSTATUS status;
2535 const char *printername;
2536 struct policy_handle pol;
2537 union spoolss_PrinterInfo info;
2538 enum winreg_Type type;
2539 union spoolss_PrinterData data;
2540 DATA_BLOB blob;
2541 struct dcerpc_binding_handle *b = cli->binding_handle;
2543 /* parse the command arguments */
2544 if (argc < 5) {
2545 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2546 " <value> <data>\n",
2547 argv[0]);
2548 return WERR_OK;
2551 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2553 type = REG_NONE;
2555 if (strequal(argv[2], "string")) {
2556 type = REG_SZ;
2559 if (strequal(argv[2], "binary")) {
2560 type = REG_BINARY;
2563 if (strequal(argv[2], "dword")) {
2564 type = REG_DWORD;
2567 if (strequal(argv[2], "multistring")) {
2568 type = REG_MULTI_SZ;
2571 if (type == REG_NONE) {
2572 printf("Unknown data type: %s\n", argv[2]);
2573 result = WERR_INVALID_PARAM;
2574 goto done;
2577 /* get a printer handle */
2579 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2580 printername,
2581 SEC_FLAG_MAXIMUM_ALLOWED,
2582 &pol);
2583 if (!W_ERROR_IS_OK(result)) {
2584 goto done;
2587 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2588 &pol,
2591 &info);
2592 if (!W_ERROR_IS_OK(result)) {
2593 goto done;
2596 printf("%s\n", current_timestring(mem_ctx, true));
2597 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2599 /* Set the printer data */
2601 switch (type) {
2602 case REG_SZ:
2603 data.string = talloc_strdup(mem_ctx, argv[4]);
2604 W_ERROR_HAVE_NO_MEMORY(data.string);
2605 break;
2606 case REG_DWORD:
2607 data.value = strtoul(argv[4], NULL, 10);
2608 break;
2609 case REG_BINARY:
2610 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2611 break;
2612 case REG_MULTI_SZ: {
2613 int i, num_strings;
2614 const char **strings = NULL;
2616 for (i=4; i<argc; i++) {
2617 if (strcmp(argv[i], "NULL") == 0) {
2618 argv[i] = "";
2620 if (!add_string_to_array(mem_ctx, argv[i],
2621 &strings,
2622 &num_strings)) {
2623 result = WERR_NOMEM;
2624 goto done;
2627 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2628 if (!data.string_array) {
2629 result = WERR_NOMEM;
2630 goto done;
2632 for (i=0; i < num_strings; i++) {
2633 data.string_array[i] = strings[i];
2635 break;
2637 default:
2638 printf("Unknown data type: %s\n", argv[2]);
2639 result = WERR_INVALID_PARAM;
2640 goto done;
2643 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2644 if (!W_ERROR_IS_OK(result)) {
2645 goto done;
2648 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2649 &pol,
2650 argv[3], /* value_name */
2651 type,
2652 blob.data,
2653 blob.length,
2654 &result);
2655 if (!NT_STATUS_IS_OK(status)) {
2656 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2657 result = ntstatus_to_werror(status);
2658 goto done;
2660 if (!W_ERROR_IS_OK(result)) {
2661 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2662 goto done;
2664 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2666 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2667 &pol,
2670 &info);
2671 if (!W_ERROR_IS_OK(result)) {
2672 goto done;
2675 printf("%s\n", current_timestring(mem_ctx, true));
2676 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2678 done:
2679 /* cleanup */
2680 if (is_valid_policy_hnd(&pol)) {
2681 WERROR _result;
2682 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2685 return result;
2688 /****************************************************************************
2689 ****************************************************************************/
2691 static void display_job_info1(struct spoolss_JobInfo1 *r)
2693 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2694 r->user_name, r->document_name, r->text_status, r->pages_printed,
2695 r->total_pages);
2698 /****************************************************************************
2699 ****************************************************************************/
2701 static void display_job_info2(struct spoolss_JobInfo2 *r)
2703 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2704 r->position, r->job_id,
2705 r->user_name, r->document_name, r->text_status, r->pages_printed,
2706 r->total_pages, r->size);
2709 /****************************************************************************
2710 ****************************************************************************/
2712 static void display_job_info3(struct spoolss_JobInfo3 *r)
2714 printf("jobid[%d], next_jobid[%d]\n",
2715 r->job_id, r->next_job_id);
2718 /****************************************************************************
2719 ****************************************************************************/
2721 static void display_job_info4(struct spoolss_JobInfo4 *r)
2723 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2724 r->position, r->job_id,
2725 r->user_name, r->document_name, r->text_status, r->pages_printed,
2726 r->total_pages, r->size, r->size_high);
2729 /****************************************************************************
2730 ****************************************************************************/
2732 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2733 TALLOC_CTX *mem_ctx, int argc,
2734 const char **argv)
2736 WERROR result;
2737 uint32_t level = 1, count, i;
2738 const char *printername;
2739 struct policy_handle hnd;
2740 union spoolss_JobInfo *info;
2741 struct dcerpc_binding_handle *b = cli->binding_handle;
2743 if (argc < 2 || argc > 3) {
2744 printf("Usage: %s printername [level]\n", argv[0]);
2745 return WERR_OK;
2748 if (argc == 3) {
2749 level = atoi(argv[2]);
2752 /* Open printer handle */
2754 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2756 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2757 printername,
2758 SEC_FLAG_MAXIMUM_ALLOWED,
2759 &hnd);
2760 if (!W_ERROR_IS_OK(result))
2761 goto done;
2763 /* Enumerate ports */
2765 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2766 &hnd,
2767 0, /* firstjob */
2768 1000, /* numjobs */
2769 level,
2771 &count,
2772 &info);
2773 if (!W_ERROR_IS_OK(result)) {
2774 goto done;
2777 for (i = 0; i < count; i++) {
2778 switch (level) {
2779 case 1:
2780 display_job_info1(&info[i].info1);
2781 break;
2782 case 2:
2783 display_job_info2(&info[i].info2);
2784 break;
2785 default:
2786 d_printf("unknown info level %d\n", level);
2787 break;
2791 done:
2792 if (is_valid_policy_hnd(&hnd)) {
2793 WERROR _result;
2794 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2797 return result;
2800 /****************************************************************************
2801 ****************************************************************************/
2803 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2804 TALLOC_CTX *mem_ctx, int argc,
2805 const char **argv)
2807 WERROR result;
2808 const char *printername;
2809 struct policy_handle hnd;
2810 uint32_t job_id;
2811 uint32_t level = 1;
2812 union spoolss_JobInfo info;
2813 struct dcerpc_binding_handle *b = cli->binding_handle;
2815 if (argc < 3 || argc > 4) {
2816 printf("Usage: %s printername job_id [level]\n", argv[0]);
2817 return WERR_OK;
2820 job_id = atoi(argv[2]);
2822 if (argc == 4) {
2823 level = atoi(argv[3]);
2826 /* Open printer handle */
2828 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2830 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2831 printername,
2832 SEC_FLAG_MAXIMUM_ALLOWED,
2833 &hnd);
2834 if (!W_ERROR_IS_OK(result)) {
2835 goto done;
2838 /* Enumerate ports */
2840 result = rpccli_spoolss_getjob(cli, mem_ctx,
2841 &hnd,
2842 job_id,
2843 level,
2845 &info);
2847 if (!W_ERROR_IS_OK(result)) {
2848 goto done;
2851 switch (level) {
2852 case 1:
2853 display_job_info1(&info.info1);
2854 break;
2855 case 2:
2856 display_job_info2(&info.info2);
2857 break;
2858 case 3:
2859 display_job_info3(&info.info3);
2860 break;
2861 case 4:
2862 display_job_info4(&info.info4);
2863 break;
2864 default:
2865 d_printf("unknown info level %d\n", level);
2866 break;
2869 done:
2870 if (is_valid_policy_hnd(&hnd)) {
2871 WERROR _result;
2872 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2875 return result;
2878 /****************************************************************************
2879 ****************************************************************************/
2881 static struct {
2882 const char *name;
2883 enum spoolss_JobControl val;
2884 } cmdvals[] = {
2885 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2886 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2887 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2888 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2889 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2890 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2891 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2892 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2893 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2896 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2898 int i;
2900 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2901 if (strequal(cmdvals[i].name, cmd)) {
2902 return cmdvals[i].val;
2905 return (enum spoolss_JobControl)atoi(cmd);
2908 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2909 TALLOC_CTX *mem_ctx, int argc,
2910 const char **argv)
2912 WERROR result;
2913 NTSTATUS status;
2914 const char *printername;
2915 struct policy_handle hnd;
2916 uint32_t job_id;
2917 enum spoolss_JobControl command;
2918 struct dcerpc_binding_handle *b = cli->binding_handle;
2920 if (argc != 4) {
2921 printf("Usage: %s printername job_id command\n", argv[0]);
2922 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2923 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2924 return WERR_OK;
2927 job_id = atoi(argv[2]);
2928 command = parse_setjob_command(argv[3]);
2930 /* Open printer handle */
2932 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2934 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2935 printername,
2936 SEC_FLAG_MAXIMUM_ALLOWED,
2937 &hnd);
2938 if (!W_ERROR_IS_OK(result)) {
2939 goto done;
2942 /* Set Job */
2944 status = dcerpc_spoolss_SetJob(b, mem_ctx,
2945 &hnd,
2946 job_id,
2947 NULL,
2948 command,
2949 &result);
2950 if (!NT_STATUS_IS_OK(status)) {
2951 result = ntstatus_to_werror(status);
2952 goto done;
2954 if (!W_ERROR_IS_OK(result)) {
2955 goto done;
2958 done:
2959 if (is_valid_policy_hnd(&hnd)) {
2960 WERROR _result;
2961 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2964 return result;
2967 /****************************************************************************
2968 ****************************************************************************/
2970 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2971 TALLOC_CTX *mem_ctx, int argc,
2972 const char **argv)
2974 WERROR result;
2975 NTSTATUS status;
2976 const char *printername;
2977 struct policy_handle hnd;
2978 uint32_t value_needed;
2979 enum winreg_Type type;
2980 uint32_t data_needed;
2981 struct dcerpc_binding_handle *b = cli->binding_handle;
2982 struct spoolss_EnumPrinterData r;
2984 if (argc != 2) {
2985 printf("Usage: %s printername\n", argv[0]);
2986 return WERR_OK;
2989 /* Open printer handle */
2991 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2993 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2994 printername,
2995 SEC_FLAG_MAXIMUM_ALLOWED,
2996 &hnd);
2997 if (!W_ERROR_IS_OK(result)) {
2998 goto done;
3001 /* Enumerate data */
3003 r.in.handle = &hnd;
3004 r.in.enum_index = 0;
3005 r.in.value_offered = 0;
3006 r.in.data_offered = 0;
3007 r.out.value_name = NULL;
3008 r.out.value_needed = &value_needed;
3009 r.out.type = &type;
3010 r.out.data = NULL;
3011 r.out.data_needed = &data_needed;
3013 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3014 if (!NT_STATUS_IS_OK(status)) {
3015 result = ntstatus_to_werror(status);
3016 goto done;
3019 if (!W_ERROR_IS_OK(r.out.result)) {
3020 result = r.out.result;
3021 goto done;
3024 r.in.data_offered = *r.out.data_needed;
3025 r.in.value_offered = *r.out.value_needed;
3026 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3027 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3029 do {
3031 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3032 if (!NT_STATUS_IS_OK(status)) {
3033 result = ntstatus_to_werror(status);
3034 goto done;
3037 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3038 result = WERR_OK;
3039 break;
3042 r.in.enum_index++;
3045 struct regval_blob *v;
3047 v = regval_compose(talloc_tos(),
3048 r.out.value_name,
3049 *r.out.type,
3050 r.out.data,
3051 r.in.data_offered);
3052 if (v == NULL) {
3053 result = WERR_NOMEM;
3054 goto done;
3057 display_reg_value(v);
3058 talloc_free(v);
3061 } while (W_ERROR_IS_OK(r.out.result));
3063 done:
3064 if (is_valid_policy_hnd(&hnd)) {
3065 WERROR _result;
3066 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3069 return result;
3072 /****************************************************************************
3073 ****************************************************************************/
3075 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3076 TALLOC_CTX *mem_ctx, int argc,
3077 const char **argv)
3079 WERROR result;
3080 uint32_t i;
3081 const char *printername;
3082 struct policy_handle hnd;
3083 uint32_t count;
3084 struct spoolss_PrinterEnumValues *info;
3085 struct dcerpc_binding_handle *b = cli->binding_handle;
3087 if (argc != 3) {
3088 printf("Usage: %s printername <keyname>\n", argv[0]);
3089 return WERR_OK;
3092 /* Open printer handle */
3094 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3096 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3097 printername,
3098 SEC_FLAG_MAXIMUM_ALLOWED,
3099 &hnd);
3100 if (!W_ERROR_IS_OK(result)) {
3101 goto done;
3104 /* Enumerate subkeys */
3106 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3107 &hnd,
3108 argv[2],
3110 &count,
3111 &info);
3112 if (!W_ERROR_IS_OK(result)) {
3113 goto done;
3116 for (i=0; i < count; i++) {
3117 display_printer_data(info[i].value_name,
3118 info[i].type,
3119 info[i].data->data,
3120 info[i].data->length);
3123 done:
3124 if (is_valid_policy_hnd(&hnd)) {
3125 WERROR _result;
3126 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3129 return result;
3132 /****************************************************************************
3133 ****************************************************************************/
3135 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3136 TALLOC_CTX *mem_ctx, int argc,
3137 const char **argv)
3139 WERROR result;
3140 const char *printername;
3141 const char *keyname = NULL;
3142 struct policy_handle hnd;
3143 const char **key_buffer = NULL;
3144 int i;
3145 uint32_t offered = 0;
3146 struct dcerpc_binding_handle *b = cli->binding_handle;
3148 if (argc < 2 || argc > 4) {
3149 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3150 return WERR_OK;
3153 if (argc >= 3) {
3154 keyname = argv[2];
3155 } else {
3156 keyname = "";
3159 if (argc == 4) {
3160 offered = atoi(argv[3]);
3163 /* Open printer handle */
3165 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3167 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3168 printername,
3169 SEC_FLAG_MAXIMUM_ALLOWED,
3170 &hnd);
3171 if (!W_ERROR_IS_OK(result)) {
3172 goto done;
3175 /* Enumerate subkeys */
3177 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3178 &hnd,
3179 keyname,
3180 &key_buffer,
3181 offered);
3183 if (!W_ERROR_IS_OK(result)) {
3184 goto done;
3187 for (i=0; key_buffer && key_buffer[i]; i++) {
3188 printf("%s\n", key_buffer[i]);
3191 done:
3193 if (is_valid_policy_hnd(&hnd)) {
3194 WERROR _result;
3195 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3198 return result;
3201 /****************************************************************************
3202 ****************************************************************************/
3204 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3205 TALLOC_CTX *mem_ctx, int argc,
3206 const char **argv)
3208 const char *printername;
3209 const char *clientname;
3210 struct policy_handle hnd;
3211 WERROR result;
3212 NTSTATUS status;
3213 struct spoolss_NotifyOption option;
3214 struct dcerpc_binding_handle *b = cli->binding_handle;
3216 if (argc != 2) {
3217 printf("Usage: %s printername\n", argv[0]);
3218 result = WERR_OK;
3219 goto done;
3222 /* Open printer */
3224 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3226 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3227 printername,
3228 SEC_FLAG_MAXIMUM_ALLOWED,
3229 &hnd);
3230 if (!W_ERROR_IS_OK(result)) {
3231 printf("Error opening %s\n", argv[1]);
3232 goto done;
3235 /* Create spool options */
3237 option.version = 2;
3238 option.count = 2;
3240 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3241 if (option.types == NULL) {
3242 result = WERR_NOMEM;
3243 goto done;
3246 option.types[0].type = PRINTER_NOTIFY_TYPE;
3247 option.types[0].count = 1;
3248 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3249 if (option.types[0].fields == NULL) {
3250 result = WERR_NOMEM;
3251 goto done;
3253 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3255 option.types[1].type = JOB_NOTIFY_TYPE;
3256 option.types[1].count = 1;
3257 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3258 if (option.types[1].fields == NULL) {
3259 result = WERR_NOMEM;
3260 goto done;
3262 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3264 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3265 if (!clientname) {
3266 result = WERR_NOMEM;
3267 goto done;
3270 /* Send rffpcnex */
3272 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3273 &hnd,
3276 clientname,
3277 123,
3278 &option,
3279 &result);
3280 if (!NT_STATUS_IS_OK(status)) {
3281 result = ntstatus_to_werror(status);
3282 goto done;
3284 if (!W_ERROR_IS_OK(result)) {
3285 printf("Error rffpcnex %s\n", argv[1]);
3286 goto done;
3289 done:
3290 if (is_valid_policy_hnd(&hnd)) {
3291 WERROR _result;
3292 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3295 return result;
3298 /****************************************************************************
3299 ****************************************************************************/
3301 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3302 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3304 union spoolss_PrinterInfo info1, info2;
3305 WERROR werror;
3306 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3308 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3309 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3310 hnd1,
3313 &info1);
3314 if ( !W_ERROR_IS_OK(werror) ) {
3315 printf("failed (%s)\n", win_errstr(werror));
3316 talloc_destroy(mem_ctx);
3317 return false;
3319 printf("ok\n");
3321 printf("Retrieving printer properties for %s...", cli2->desthost);
3322 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3323 hnd2,
3326 &info2);
3327 if ( !W_ERROR_IS_OK(werror) ) {
3328 printf("failed (%s)\n", win_errstr(werror));
3329 talloc_destroy(mem_ctx);
3330 return false;
3332 printf("ok\n");
3334 talloc_destroy(mem_ctx);
3336 return true;
3339 /****************************************************************************
3340 ****************************************************************************/
3342 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3343 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3345 union spoolss_PrinterInfo info1, info2;
3346 WERROR werror;
3347 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3348 struct security_descriptor *sd1, *sd2;
3349 bool result = true;
3352 printf("Retrieving printer security for %s...", cli1->desthost);
3353 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3354 hnd1,
3357 &info1);
3358 if ( !W_ERROR_IS_OK(werror) ) {
3359 printf("failed (%s)\n", win_errstr(werror));
3360 result = false;
3361 goto done;
3363 printf("ok\n");
3365 printf("Retrieving printer security for %s...", cli2->desthost);
3366 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3367 hnd2,
3370 &info2);
3371 if ( !W_ERROR_IS_OK(werror) ) {
3372 printf("failed (%s)\n", win_errstr(werror));
3373 result = false;
3374 goto done;
3376 printf("ok\n");
3379 printf("++ ");
3381 sd1 = info1.info3.secdesc;
3382 sd2 = info2.info3.secdesc;
3384 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3385 printf("NULL secdesc!\n");
3386 result = false;
3387 goto done;
3390 if (!security_descriptor_equal( sd1, sd2 ) ) {
3391 printf("Security Descriptors *not* equal!\n");
3392 result = false;
3393 goto done;
3396 printf("Security descriptors match\n");
3398 done:
3399 talloc_destroy(mem_ctx);
3400 return result;
3404 /****************************************************************************
3405 ****************************************************************************/
3407 extern struct user_auth_info *rpcclient_auth_info;
3409 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3410 TALLOC_CTX *mem_ctx, int argc,
3411 const char **argv)
3413 const char *printername;
3414 char *printername_path = NULL;
3415 struct cli_state *cli_server2 = NULL;
3416 struct rpc_pipe_client *cli2 = NULL;
3417 struct policy_handle hPrinter1, hPrinter2;
3418 NTSTATUS nt_status;
3419 WERROR werror;
3421 if ( argc != 3 ) {
3422 printf("Usage: %s <printer> <server>\n", argv[0]);
3423 return WERR_OK;
3426 printername = argv[1];
3428 /* first get the connection to the remote server */
3430 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3431 NULL, 0,
3432 "IPC$", "IPC",
3433 get_cmdline_auth_info_username(rpcclient_auth_info),
3434 lp_workgroup(),
3435 get_cmdline_auth_info_password(rpcclient_auth_info),
3436 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3437 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3439 if ( !NT_STATUS_IS_OK(nt_status) )
3440 return WERR_GENERAL_FAILURE;
3442 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3443 &cli2);
3444 if (!NT_STATUS_IS_OK(nt_status)) {
3445 printf("failed to open spoolss pipe on server %s (%s)\n",
3446 argv[2], nt_errstr(nt_status));
3447 return WERR_GENERAL_FAILURE;
3450 /* now open up both printers */
3452 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3454 printf("Opening %s...", printername_path);
3456 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3457 printername_path,
3458 PRINTER_ALL_ACCESS,
3459 &hPrinter1);
3460 if ( !W_ERROR_IS_OK(werror) ) {
3461 printf("failed (%s)\n", win_errstr(werror));
3462 goto done;
3464 printf("ok\n");
3466 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3468 printf("Opening %s...", printername_path);
3469 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3470 printername_path,
3471 PRINTER_ALL_ACCESS,
3472 &hPrinter2);
3473 if ( !W_ERROR_IS_OK(werror) ) {
3474 printf("failed (%s)\n", win_errstr(werror));
3475 goto done;
3477 printf("ok\n");
3479 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3480 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3481 #if 0
3482 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3483 #endif
3486 done:
3487 /* cleanup */
3489 printf("Closing printers...");
3491 WERROR _result;
3492 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3493 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3495 printf("ok\n");
3497 /* close the second remote connection */
3499 cli_shutdown( cli_server2 );
3500 return WERR_OK;
3503 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3505 printf("print_processor_name: %s\n", r->print_processor_name);
3508 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3509 TALLOC_CTX *mem_ctx, int argc,
3510 const char **argv)
3512 WERROR werror;
3513 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3514 uint32_t num_procs, level = 1, i;
3515 union spoolss_PrintProcessorInfo *procs;
3517 /* Parse the command arguments */
3519 if (argc < 1 || argc > 4) {
3520 printf ("Usage: %s [environment] [level]\n", argv[0]);
3521 return WERR_OK;
3524 if (argc >= 2) {
3525 environment = argv[1];
3528 if (argc == 3) {
3529 level = atoi(argv[2]);
3532 /* Enumerate Print Processors */
3534 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3535 cli->srv_name_slash,
3536 environment,
3537 level,
3539 &num_procs,
3540 &procs);
3541 if (!W_ERROR_IS_OK(werror))
3542 goto done;
3544 /* Display output */
3546 for (i = 0; i < num_procs; i++) {
3547 switch (level) {
3548 case 1:
3549 display_proc_info1(&procs[i].info1);
3550 break;
3554 done:
3555 return werror;
3558 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3560 printf("name_array: %s\n", r->name_array);
3563 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3564 TALLOC_CTX *mem_ctx, int argc,
3565 const char **argv)
3567 WERROR werror;
3568 const char *print_processor_name = "winprint";
3569 uint32_t num_procs, level = 1, i;
3570 union spoolss_PrintProcDataTypesInfo *procs;
3572 /* Parse the command arguments */
3574 if (argc < 1 || argc > 4) {
3575 printf ("Usage: %s [environment] [level]\n", argv[0]);
3576 return WERR_OK;
3579 if (argc >= 2) {
3580 print_processor_name = argv[1];
3583 if (argc == 3) {
3584 level = atoi(argv[2]);
3587 /* Enumerate Print Processor Data Types */
3589 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3590 cli->srv_name_slash,
3591 print_processor_name,
3592 level,
3594 &num_procs,
3595 &procs);
3596 if (!W_ERROR_IS_OK(werror))
3597 goto done;
3599 /* Display output */
3601 for (i = 0; i < num_procs; i++) {
3602 switch (level) {
3603 case 1:
3604 display_proc_data_types_info1(&procs[i].info1);
3605 break;
3609 done:
3610 return werror;
3613 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3615 printf("monitor_name: %s\n", r->monitor_name);
3618 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3620 printf("monitor_name: %s\n", r->monitor_name);
3621 printf("environment: %s\n", r->environment);
3622 printf("dll_name: %s\n", r->dll_name);
3625 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3626 TALLOC_CTX *mem_ctx, int argc,
3627 const char **argv)
3629 WERROR werror;
3630 uint32_t count, level = 1, i;
3631 union spoolss_MonitorInfo *info;
3633 /* Parse the command arguments */
3635 if (argc > 2) {
3636 printf("Usage: %s [level]\n", argv[0]);
3637 return WERR_OK;
3640 if (argc == 2) {
3641 level = atoi(argv[1]);
3644 /* Enumerate Print Monitors */
3646 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3647 cli->srv_name_slash,
3648 level,
3650 &count,
3651 &info);
3652 if (!W_ERROR_IS_OK(werror)) {
3653 goto done;
3656 /* Display output */
3658 for (i = 0; i < count; i++) {
3659 switch (level) {
3660 case 1:
3661 display_monitor1(&info[i].info1);
3662 break;
3663 case 2:
3664 display_monitor2(&info[i].info2);
3665 break;
3669 done:
3670 return werror;
3673 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3674 TALLOC_CTX *mem_ctx, int argc,
3675 const char **argv)
3677 WERROR result;
3678 NTSTATUS status;
3679 struct policy_handle handle, gdi_handle;
3680 const char *printername;
3681 struct spoolss_DevmodeContainer devmode_ctr;
3682 struct dcerpc_binding_handle *b = cli->binding_handle;
3684 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3686 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3687 printername,
3688 SEC_FLAG_MAXIMUM_ALLOWED,
3689 &handle);
3690 if (!W_ERROR_IS_OK(result)) {
3691 return result;
3694 ZERO_STRUCT(devmode_ctr);
3696 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3697 &handle,
3698 &gdi_handle,
3699 &devmode_ctr,
3700 &result);
3701 if (!NT_STATUS_IS_OK(status)) {
3702 result = ntstatus_to_werror(status);
3703 goto done;
3705 if (!W_ERROR_IS_OK(result)) {
3706 goto done;
3709 done:
3710 if (is_valid_policy_hnd(&gdi_handle)) {
3711 WERROR _result;
3712 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3714 if (is_valid_policy_hnd(&handle)) {
3715 WERROR _result;
3716 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3719 return result;
3722 /* List of commands exported by this module */
3723 struct cmd_set spoolss_commands[] = {
3725 { "SPOOLSS" },
3727 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3728 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3729 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3730 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3731 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3732 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3733 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3734 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3735 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3736 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3737 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3738 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3739 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3740 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3741 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3742 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3743 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3744 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3745 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3746 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3747 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3748 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3749 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3750 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3751 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3752 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3753 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3754 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3755 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3756 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3757 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3758 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3759 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3760 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3761 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3762 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3764 { NULL }