s3-rpcclient: Fix bug #7880: cmd_spoolss_deletedriver() returned without checking...
[Samba/gebeck_regimport.git] / source3 / rpcclient / cmd_spoolss.c
blobf9d7b6560b93e2abfea3e2e14c1562af1f16cabf
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/cli_spoolss.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
30 #include "registry.h"
31 #include "registry/reg_objects.h"
32 #include "nt_printing.h"
34 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
35 { \
36 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
37 _cli->srv_name_slash, _arg); \
38 W_ERROR_HAVE_NO_MEMORY(_printername); \
41 /* The version int is used by getdrivers. Note that
42 all architecture strings that support mutliple
43 versions must be grouped together since enumdrivers
44 uses this property to prevent issuing multiple
45 enumdriver calls for the same arch */
48 static const struct print_architecture_table_node archi_table[]= {
50 {"Windows 4.0", "WIN40", 0 },
51 {"Windows NT x86", "W32X86", 2 },
52 {"Windows NT x86", "W32X86", 3 },
53 {"Windows NT R4000", "W32MIPS", 2 },
54 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
55 {"Windows NT PowerPC", "W32PPC", 2 },
56 {"Windows IA64", "IA64", 3 },
57 {"Windows x64", "x64", 3 },
58 {NULL, "", -1 }
61 /**
62 * @file
64 * rpcclient module for SPOOLSS rpc pipe.
66 * This generally just parses and checks command lines, and then calls
67 * a cli_spoolss function.
68 **/
70 /****************************************************************************
71 function to do the mapping between the long architecture name and
72 the short one.
73 ****************************************************************************/
75 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
77 int i=-1;
79 DEBUG(107,("Getting architecture dependant directory\n"));
80 do {
81 i++;
82 } while ( (archi_table[i].long_archi!=NULL ) &&
83 StrCaseCmp(long_archi, archi_table[i].long_archi) );
85 if (archi_table[i].long_archi==NULL) {
86 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
87 return NULL;
90 /* this might be client code - but shouldn't this be an fstrcpy etc? */
93 DEBUGADD(108,("index: [%d]\n", i));
94 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
95 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
97 return archi_table[i].short_archi;
100 /****************************************************************************
101 ****************************************************************************/
103 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
104 TALLOC_CTX *mem_ctx,
105 int argc, const char **argv)
107 WERROR werror;
108 struct policy_handle hnd;
109 uint32_t access_mask = PRINTER_ALL_ACCESS;
111 if (argc < 2) {
112 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
113 return WERR_OK;
116 if (argc >= 3) {
117 sscanf(argv[2], "%x", &access_mask);
120 /* Open the printer handle */
122 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
123 argv[1],
124 access_mask,
125 &hnd);
126 if (W_ERROR_IS_OK(werror)) {
127 printf("Printer %s opened successfully\n", argv[1]);
128 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
130 if (!W_ERROR_IS_OK(werror)) {
131 printf("Error closing printer handle! (%s)\n",
132 get_dos_error_msg(werror));
136 return werror;
139 /****************************************************************************
140 ****************************************************************************/
142 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
143 TALLOC_CTX *mem_ctx,
144 int argc, const char **argv)
146 WERROR werror;
147 struct policy_handle hnd;
148 uint32_t access_mask = PRINTER_ALL_ACCESS;
149 NTSTATUS status;
150 struct spoolss_DevmodeContainer devmode_ctr;
152 ZERO_STRUCT(devmode_ctr);
154 if (argc < 2) {
155 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
156 return WERR_OK;
159 if (argc >= 3) {
160 sscanf(argv[2], "%x", &access_mask);
163 /* Open the printer handle */
165 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
166 argv[1],
167 NULL,
168 devmode_ctr,
169 access_mask,
170 &hnd,
171 &werror);
172 if (W_ERROR_IS_OK(werror)) {
173 printf("Printer %s opened successfully\n", argv[1]);
174 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
176 if (!W_ERROR_IS_OK(werror)) {
177 printf("Error closing printer handle! (%s)\n",
178 get_dos_error_msg(werror));
182 return werror;
185 /****************************************************************************
186 ****************************************************************************/
188 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
190 if (!r)
191 return;
193 printf("\tprintername:[%s]\n", r->printername);
194 printf("\tservername:[%s]\n", r->servername);
195 printf("\tcjobs:[0x%x]\n", r->cjobs);
196 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
197 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
198 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
199 r->time.day, r->time.day_of_week);
200 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
201 r->time.second, r->time.millisecond);
203 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
204 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
206 printf("\tversion:[0x%x]\n", r->version);
207 printf("\tfree_build:[0x%x]\n", r->free_build);
208 printf("\tspooling:[0x%x]\n", r->spooling);
209 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
210 printf("\tsession_counter:[0x%x]\n", r->session_counter);
211 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
212 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
213 printf("\tjob_error:[0x%x]\n", r->job_error);
214 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
215 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
216 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
217 printf("\tchange_id:[0x%x]\n", r->change_id);
218 printf("\tlast_error: %s\n", win_errstr(r->last_error));
219 printf("\tstatus:[0x%x]\n", r->status);
220 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
221 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
222 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
223 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
224 printf("\tref_ic:[0x%x]\n", r->ref_ic);
225 printf("\treserved2:[0x%x]\n", r->reserved2);
226 printf("\treserved3:[0x%x]\n", r->reserved3);
228 printf("\n");
231 /****************************************************************************
232 ****************************************************************************/
234 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
236 printf("\tflags:[0x%x]\n", r->flags);
237 printf("\tname:[%s]\n", r->name);
238 printf("\tdescription:[%s]\n", r->description);
239 printf("\tcomment:[%s]\n", r->comment);
241 printf("\n");
244 /****************************************************************************
245 ****************************************************************************/
247 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
249 printf("\tservername:[%s]\n", r->servername);
250 printf("\tprintername:[%s]\n", r->printername);
251 printf("\tsharename:[%s]\n", r->sharename);
252 printf("\tportname:[%s]\n", r->portname);
253 printf("\tdrivername:[%s]\n", r->drivername);
254 printf("\tcomment:[%s]\n", r->comment);
255 printf("\tlocation:[%s]\n", r->location);
256 printf("\tsepfile:[%s]\n", r->sepfile);
257 printf("\tprintprocessor:[%s]\n", r->printprocessor);
258 printf("\tdatatype:[%s]\n", r->datatype);
259 printf("\tparameters:[%s]\n", r->parameters);
260 printf("\tattributes:[0x%x]\n", r->attributes);
261 printf("\tpriority:[0x%x]\n", r->priority);
262 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
263 printf("\tstarttime:[0x%x]\n", r->starttime);
264 printf("\tuntiltime:[0x%x]\n", r->untiltime);
265 printf("\tstatus:[0x%x]\n", r->status);
266 printf("\tcjobs:[0x%x]\n", r->cjobs);
267 printf("\taverageppm:[0x%x]\n", r->averageppm);
269 if (r->secdesc)
270 display_sec_desc(r->secdesc);
272 printf("\n");
275 /****************************************************************************
276 ****************************************************************************/
278 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
280 display_sec_desc(r->secdesc);
282 printf("\n");
285 /****************************************************************************
286 ****************************************************************************/
288 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
290 printf("\tservername:[%s]\n", r->servername);
291 printf("\tprintername:[%s]\n", r->printername);
292 printf("\tattributes:[0x%x]\n", r->attributes);
293 printf("\n");
296 /****************************************************************************
297 ****************************************************************************/
299 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
301 printf("\tprintername:[%s]\n", r->printername);
302 printf("\tportname:[%s]\n", r->portname);
303 printf("\tattributes:[0x%x]\n", r->attributes);
304 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
305 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
306 printf("\n");
309 /****************************************************************************
310 ****************************************************************************/
312 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
314 printf("\tstatus:[0x%x]\n", r->status);
315 printf("\n");
318 /****************************************************************************
319 ****************************************************************************/
321 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
323 printf("\tguid:[%s]\n", r->guid);
324 printf("\taction:[0x%x]\n", r->action);
325 printf("\n");
328 /****************************************************************************
329 ****************************************************************************/
331 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
332 TALLOC_CTX *mem_ctx,
333 int argc, const char **argv)
335 WERROR result;
336 uint32_t level = 1;
337 union spoolss_PrinterInfo *info;
338 uint32_t i, count;
339 const char *name;
340 uint32_t flags = PRINTER_ENUM_LOCAL;
342 if (argc > 4) {
343 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
344 return WERR_OK;
347 if (argc >= 2) {
348 level = atoi(argv[1]);
351 if (argc >= 3) {
352 name = argv[2];
353 } else {
354 name = cli->srv_name_slash;
357 if (argc == 4) {
358 flags = atoi(argv[3]);
361 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
362 flags,
363 name,
364 level,
366 &count,
367 &info);
368 if (W_ERROR_IS_OK(result)) {
370 if (!count) {
371 printf ("No printers returned.\n");
372 goto done;
375 for (i = 0; i < count; i++) {
376 switch (level) {
377 case 0:
378 display_print_info0(&info[i].info0);
379 break;
380 case 1:
381 display_print_info1(&info[i].info1);
382 break;
383 case 2:
384 display_print_info2(&info[i].info2);
385 break;
386 case 3:
387 display_print_info3(&info[i].info3);
388 break;
389 case 4:
390 display_print_info4(&info[i].info4);
391 break;
392 case 5:
393 display_print_info5(&info[i].info5);
394 break;
395 case 6:
396 display_print_info6(&info[i].info6);
397 break;
398 default:
399 printf("unknown info level %d\n", level);
400 goto done;
404 done:
406 return result;
409 /****************************************************************************
410 ****************************************************************************/
412 static void display_port_info_1(struct spoolss_PortInfo1 *r)
414 printf("\tPort Name:\t[%s]\n", r->port_name);
417 /****************************************************************************
418 ****************************************************************************/
420 static void display_port_info_2(struct spoolss_PortInfo2 *r)
422 printf("\tPort Name:\t[%s]\n", r->port_name);
423 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
424 printf("\tDescription:\t[%s]\n", r->description);
425 printf("\tPort Type:\t" );
426 if (r->port_type) {
427 int comma = 0; /* hack */
428 printf( "[" );
429 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
430 printf( "Read" );
431 comma = 1;
433 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
434 printf( "%sWrite", comma ? ", " : "" );
435 comma = 1;
437 /* These two have slightly different interpretations
438 on 95/98/ME but I'm disregarding that for now */
439 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
440 printf( "%sRedirected", comma ? ", " : "" );
441 comma = 1;
443 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
444 printf( "%sNet-Attached", comma ? ", " : "" );
446 printf( "]\n" );
447 } else {
448 printf( "[Unset]\n" );
450 printf("\tReserved:\t[%d]\n", r->reserved);
451 printf("\n");
454 /****************************************************************************
455 ****************************************************************************/
457 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
458 TALLOC_CTX *mem_ctx, int argc,
459 const char **argv)
461 WERROR result;
462 uint32_t level = 1;
463 uint32_t count;
464 union spoolss_PortInfo *info;
466 if (argc > 2) {
467 printf("Usage: %s [level]\n", argv[0]);
468 return WERR_OK;
471 if (argc == 2) {
472 level = atoi(argv[1]);
475 /* Enumerate ports */
477 result = rpccli_spoolss_enumports(cli, mem_ctx,
478 cli->srv_name_slash,
479 level,
481 &count,
482 &info);
483 if (W_ERROR_IS_OK(result)) {
484 int i;
486 for (i = 0; i < count; i++) {
487 switch (level) {
488 case 1:
489 display_port_info_1(&info[i].info1);
490 break;
491 case 2:
492 display_port_info_2(&info[i].info2);
493 break;
494 default:
495 printf("unknown info level %d\n", level);
496 break;
501 return result;
504 /****************************************************************************
505 ****************************************************************************/
507 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
508 TALLOC_CTX *mem_ctx,
509 int argc, const char **argv)
511 struct policy_handle pol;
512 WERROR result;
513 NTSTATUS status;
514 uint32_t info_level = 2;
515 union spoolss_PrinterInfo info;
516 struct spoolss_SetPrinterInfoCtr info_ctr;
517 struct spoolss_SetPrinterInfo2 info2;
518 const char *printername, *comment = NULL;
519 struct spoolss_DevmodeContainer devmode_ctr;
520 struct sec_desc_buf secdesc_ctr;
522 if (argc == 1 || argc > 3) {
523 printf("Usage: %s printername comment\n", argv[0]);
525 return WERR_OK;
528 /* Open a printer handle */
529 if (argc == 3) {
530 comment = argv[2];
533 ZERO_STRUCT(devmode_ctr);
534 ZERO_STRUCT(secdesc_ctr);
536 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
538 /* get a printer handle */
539 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
540 printername,
541 PRINTER_ALL_ACCESS,
542 &pol);
543 if (!W_ERROR_IS_OK(result))
544 goto done;
546 /* Get printer info */
547 result = rpccli_spoolss_getprinter(cli, mem_ctx,
548 &pol,
549 info_level,
551 &info);
552 if (!W_ERROR_IS_OK(result))
553 goto done;
556 /* Modify the comment. */
557 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
558 info2.comment = comment;
560 info_ctr.level = 2;
561 info_ctr.info.info2 = &info2;
563 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
564 &pol,
565 &info_ctr,
566 &devmode_ctr,
567 &secdesc_ctr,
568 0, /* command */
569 &result);
570 if (W_ERROR_IS_OK(result))
571 printf("Success in setting comment.\n");
573 done:
574 if (is_valid_policy_hnd(&pol))
575 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
577 return result;
580 /****************************************************************************
581 ****************************************************************************/
583 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
584 TALLOC_CTX *mem_ctx,
585 int argc, const char **argv)
587 struct policy_handle pol;
588 WERROR result;
589 NTSTATUS status;
590 uint32_t info_level = 2;
591 union spoolss_PrinterInfo info;
592 const char *printername,
593 *new_printername = NULL;
594 struct spoolss_SetPrinterInfoCtr info_ctr;
595 struct spoolss_SetPrinterInfo2 info2;
596 struct spoolss_DevmodeContainer devmode_ctr;
597 struct sec_desc_buf secdesc_ctr;
599 ZERO_STRUCT(devmode_ctr);
600 ZERO_STRUCT(secdesc_ctr);
602 if (argc == 1 || argc > 3) {
603 printf("Usage: %s printername new_printername\n", argv[0]);
605 return WERR_OK;
608 /* Open a printer handle */
609 if (argc == 3) {
610 new_printername = argv[2];
613 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
615 /* get a printer handle */
616 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
617 printername,
618 PRINTER_ALL_ACCESS,
619 &pol);
620 if (!W_ERROR_IS_OK(result))
621 goto done;
623 /* Get printer info */
624 result = rpccli_spoolss_getprinter(cli, mem_ctx,
625 &pol,
626 info_level,
628 &info);
629 if (!W_ERROR_IS_OK(result))
630 goto done;
632 /* Modify the printername. */
633 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
634 info2.printername = new_printername;
636 info_ctr.level = 2;
637 info_ctr.info.info2 = &info2;
639 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
640 &pol,
641 &info_ctr,
642 &devmode_ctr,
643 &secdesc_ctr,
644 0, /* command */
645 &result);
646 if (W_ERROR_IS_OK(result))
647 printf("Success in setting printername.\n");
649 done:
650 if (is_valid_policy_hnd(&pol))
651 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
653 return result;
656 /****************************************************************************
657 ****************************************************************************/
659 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
660 TALLOC_CTX *mem_ctx,
661 int argc, const char **argv)
663 struct policy_handle pol;
664 WERROR result;
665 uint32_t level = 1;
666 const char *printername;
667 union spoolss_PrinterInfo info;
669 if (argc == 1 || argc > 3) {
670 printf("Usage: %s <printername> [level]\n", argv[0]);
671 return WERR_OK;
674 /* Open a printer handle */
675 if (argc == 3) {
676 level = atoi(argv[2]);
679 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
681 /* get a printer handle */
683 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
684 printername,
685 SEC_FLAG_MAXIMUM_ALLOWED,
686 &pol);
687 if (!W_ERROR_IS_OK(result)) {
688 goto done;
691 /* Get printer info */
693 result = rpccli_spoolss_getprinter(cli, mem_ctx,
694 &pol,
695 level,
697 &info);
698 if (!W_ERROR_IS_OK(result)) {
699 goto done;
702 /* Display printer info */
703 switch (level) {
704 case 0:
705 display_print_info0(&info.info0);
706 break;
707 case 1:
708 display_print_info1(&info.info1);
709 break;
710 case 2:
711 display_print_info2(&info.info2);
712 break;
713 case 3:
714 display_print_info3(&info.info3);
715 break;
716 case 4:
717 display_print_info4(&info.info4);
718 break;
719 case 5:
720 display_print_info5(&info.info5);
721 break;
722 case 6:
723 display_print_info6(&info.info6);
724 break;
725 case 7:
726 display_print_info7(&info.info7);
727 break;
728 default:
729 printf("unknown info level %d\n", level);
730 break;
732 done:
733 if (is_valid_policy_hnd(&pol)) {
734 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
737 return result;
740 /****************************************************************************
741 ****************************************************************************/
743 static void display_reg_value(struct regval_blob *value)
745 const char *text = NULL;
746 DATA_BLOB blob;
748 switch(regval_type(value)) {
749 case REG_DWORD:
750 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
751 *((uint32_t *) regval_data_p(value)));
752 break;
753 case REG_SZ:
754 blob = data_blob_const(regval_data_p(value), regval_size(value));
755 pull_reg_sz(talloc_tos(), &blob, &text);
756 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
757 break;
758 case REG_BINARY: {
759 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
760 size_t i, len;
761 printf("%s: REG_BINARY:", regval_name(value));
762 len = strlen(hex);
763 for (i=0; i<len; i++) {
764 if (hex[i] == '\0') {
765 break;
767 if (i%40 == 0) {
768 putchar('\n');
770 putchar(hex[i]);
772 TALLOC_FREE(hex);
773 putchar('\n');
774 break;
776 case REG_MULTI_SZ: {
777 uint32_t i;
778 const char **values;
779 blob = data_blob_const(regval_data_p(value), regval_size(value));
781 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
782 d_printf("pull_reg_multi_sz failed\n");
783 break;
786 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
787 for (i=0; values[i] != NULL; i++) {
788 d_printf("%s\n", values[i]);
790 TALLOC_FREE(values);
791 break;
793 default:
794 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
799 /****************************************************************************
800 ****************************************************************************/
802 static void display_printer_data(const char *v,
803 enum winreg_Type type,
804 uint8_t *data,
805 uint32_t length)
807 int i;
808 union spoolss_PrinterData r;
809 DATA_BLOB blob = data_blob_const(data, length);
810 WERROR result;
812 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
813 if (!W_ERROR_IS_OK(result)) {
814 return;
817 switch (type) {
818 case REG_DWORD:
819 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
820 break;
821 case REG_SZ:
822 printf("%s: REG_SZ: %s\n", v, r.string);
823 break;
824 case REG_BINARY: {
825 char *hex = hex_encode_talloc(NULL,
826 r.binary.data, r.binary.length);
827 size_t len;
828 printf("%s: REG_BINARY:", v);
829 len = strlen(hex);
830 for (i=0; i<len; i++) {
831 if (hex[i] == '\0') {
832 break;
834 if (i%40 == 0) {
835 putchar('\n');
837 putchar(hex[i]);
839 TALLOC_FREE(hex);
840 putchar('\n');
841 break;
843 case REG_MULTI_SZ:
844 printf("%s: REG_MULTI_SZ: ", v);
845 for (i=0; r.string_array[i] != NULL; i++) {
846 printf("%s ", r.string_array[i]);
848 printf("\n");
849 break;
850 default:
851 printf("%s: unknown type 0x%02x:\n", v, type);
852 break;
856 /****************************************************************************
857 ****************************************************************************/
859 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
860 TALLOC_CTX *mem_ctx,
861 int argc, const char **argv)
863 struct policy_handle pol;
864 WERROR result;
865 fstring printername;
866 const char *valuename;
867 enum winreg_Type type;
868 uint8_t *data;
869 uint32_t needed;
871 if (argc != 3) {
872 printf("Usage: %s <printername> <valuename>\n", argv[0]);
873 printf("<printername> of . queries print server\n");
874 return WERR_OK;
876 valuename = argv[2];
878 /* Open a printer handle */
880 if (strncmp(argv[1], ".", sizeof(".")) == 0)
881 fstrcpy(printername, cli->srv_name_slash);
882 else
883 slprintf(printername, sizeof(printername)-1, "%s\\%s",
884 cli->srv_name_slash, argv[1]);
886 /* get a printer handle */
888 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
889 printername,
890 SEC_FLAG_MAXIMUM_ALLOWED,
891 &pol);
892 if (!W_ERROR_IS_OK(result))
893 goto done;
895 /* Get printer info */
897 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
898 &pol,
899 valuename,
901 &type,
902 &needed,
903 &data);
904 if (!W_ERROR_IS_OK(result))
905 goto done;
907 /* Display printer data */
909 display_printer_data(valuename, type, data, needed);
911 done:
912 if (is_valid_policy_hnd(&pol))
913 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
915 return result;
918 /****************************************************************************
919 ****************************************************************************/
921 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
922 TALLOC_CTX *mem_ctx,
923 int argc, const char **argv)
925 struct policy_handle pol;
926 WERROR result;
927 NTSTATUS status;
928 fstring printername;
929 const char *valuename, *keyname;
931 enum winreg_Type type;
932 uint8_t *data = NULL;
933 uint32_t offered = 0;
934 uint32_t needed;
936 if (argc != 4) {
937 printf("Usage: %s <printername> <keyname> <valuename>\n",
938 argv[0]);
939 printf("<printername> of . queries print server\n");
940 return WERR_OK;
942 valuename = argv[3];
943 keyname = argv[2];
945 /* Open a printer handle */
947 if (strncmp(argv[1], ".", sizeof(".")) == 0)
948 fstrcpy(printername, cli->srv_name_slash);
949 else
950 slprintf(printername, sizeof(printername)-1, "%s\\%s",
951 cli->srv_name_slash, argv[1]);
953 /* get a printer handle */
955 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
956 printername,
957 SEC_FLAG_MAXIMUM_ALLOWED,
958 &pol);
959 if (!W_ERROR_IS_OK(result))
960 goto done;
962 /* Get printer info */
964 data = talloc_zero_array(mem_ctx, uint8_t, offered);
965 if (!data) {
966 goto done;
969 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
970 &pol,
971 keyname,
972 valuename,
973 &type,
974 data,
975 offered,
976 &needed,
977 &result);
978 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
979 offered = needed;
980 data = talloc_zero_array(mem_ctx, uint8_t, offered);
981 if (!data) {
982 goto done;
984 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
985 &pol,
986 keyname,
987 valuename,
988 &type,
989 data,
990 offered,
991 &needed,
992 &result);
995 if (!NT_STATUS_IS_OK(status)) {
996 goto done;
999 if (!W_ERROR_IS_OK(result))
1000 goto done;
1002 /* Display printer data */
1004 display_printer_data(valuename, type, data, needed);
1007 done:
1008 if (is_valid_policy_hnd(&pol))
1009 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1011 return result;
1014 /****************************************************************************
1015 ****************************************************************************/
1017 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1019 if (!r) {
1020 return;
1023 printf("Printer Driver Info 1:\n");
1024 printf("\tDriver Name: [%s]\n", r->driver_name);
1025 printf("\n");
1028 /****************************************************************************
1029 ****************************************************************************/
1031 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1033 if (!r) {
1034 return;
1037 printf("Printer Driver Info 2:\n");
1038 printf("\tVersion: [%x]\n", r->version);
1039 printf("\tDriver Name: [%s]\n", r->driver_name);
1040 printf("\tArchitecture: [%s]\n", r->architecture);
1041 printf("\tDriver Path: [%s]\n", r->driver_path);
1042 printf("\tDatafile: [%s]\n", r->data_file);
1043 printf("\tConfigfile: [%s]\n", r->config_file);
1044 printf("\n");
1047 /****************************************************************************
1048 ****************************************************************************/
1050 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1052 int i;
1054 if (!r) {
1055 return;
1058 printf("Printer Driver Info 3:\n");
1059 printf("\tVersion: [%x]\n", r->version);
1060 printf("\tDriver Name: [%s]\n", r->driver_name);
1061 printf("\tArchitecture: [%s]\n", r->architecture);
1062 printf("\tDriver Path: [%s]\n", r->driver_path);
1063 printf("\tDatafile: [%s]\n", r->data_file);
1064 printf("\tConfigfile: [%s]\n", r->config_file);
1065 printf("\tHelpfile: [%s]\n", r->help_file);
1067 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1068 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1071 printf("\tMonitorname: [%s]\n", r->monitor_name);
1072 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1073 printf("\n");
1076 /****************************************************************************
1077 ****************************************************************************/
1079 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1081 int i;
1083 if (!r) {
1084 return;
1087 printf("Printer Driver Info 4:\n");
1088 printf("\tVersion: [%x]\n", r->version);
1089 printf("\tDriver Name: [%s]\n", r->driver_name);
1090 printf("\tArchitecture: [%s]\n", r->architecture);
1091 printf("\tDriver Path: [%s]\n", r->driver_path);
1092 printf("\tDatafile: [%s]\n", r->data_file);
1093 printf("\tConfigfile: [%s]\n", r->config_file);
1094 printf("\tHelpfile: [%s]\n", r->help_file);
1096 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1097 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1100 printf("\tMonitorname: [%s]\n", r->monitor_name);
1101 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1103 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1104 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1106 printf("\n");
1109 /****************************************************************************
1110 ****************************************************************************/
1112 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1114 if (!r) {
1115 return;
1118 printf("Printer Driver Info 5:\n");
1119 printf("\tVersion: [%x]\n", r->version);
1120 printf("\tDriver Name: [%s]\n", r->driver_name);
1121 printf("\tArchitecture: [%s]\n", r->architecture);
1122 printf("\tDriver Path: [%s]\n", r->driver_path);
1123 printf("\tDatafile: [%s]\n", r->data_file);
1124 printf("\tConfigfile: [%s]\n", r->config_file);
1125 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1126 printf("\tConfig Version: [0x%x]\n", r->config_version);
1127 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1128 printf("\n");
1131 /****************************************************************************
1132 ****************************************************************************/
1134 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1136 int i;
1138 if (!r) {
1139 return;
1142 printf("Printer Driver Info 6:\n");
1143 printf("\tVersion: [%x]\n", r->version);
1144 printf("\tDriver Name: [%s]\n", r->driver_name);
1145 printf("\tArchitecture: [%s]\n", r->architecture);
1146 printf("\tDriver Path: [%s]\n", r->driver_path);
1147 printf("\tDatafile: [%s]\n", r->data_file);
1148 printf("\tConfigfile: [%s]\n", r->config_file);
1149 printf("\tHelpfile: [%s]\n", r->help_file);
1151 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1152 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1155 printf("\tMonitorname: [%s]\n", r->monitor_name);
1156 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1158 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1159 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1162 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1163 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1164 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1165 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1166 printf("\tHardware ID: [%s]\n", r->hardware_id);
1167 printf("\tProvider: [%s]\n", r->provider);
1169 printf("\n");
1172 /****************************************************************************
1173 ****************************************************************************/
1175 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1177 int i;
1179 if (!r) {
1180 return;
1183 printf("Printer Driver Info 8:\n");
1184 printf("\tVersion: [%x]\n", r->version);
1185 printf("\tDriver Name: [%s]\n", r->driver_name);
1186 printf("\tArchitecture: [%s]\n", r->architecture);
1187 printf("\tDriver Path: [%s]\n", r->driver_path);
1188 printf("\tDatafile: [%s]\n", r->data_file);
1189 printf("\tConfigfile: [%s]\n", r->config_file);
1190 printf("\tHelpfile: [%s]\n", r->help_file);
1191 printf("\tMonitorname: [%s]\n", r->monitor_name);
1192 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1194 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1195 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1198 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1199 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1202 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1203 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1204 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1205 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1206 printf("\tHardware ID: [%s]\n", r->hardware_id);
1207 printf("\tProvider: [%s]\n", r->provider);
1208 printf("\tPrint Processor: [%s]\n", r->print_processor);
1209 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1210 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1211 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1213 printf("\tInf Path: [%s]\n", r->inf_path);
1214 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1215 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1216 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1218 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1219 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1220 (long long unsigned int)r->min_inbox_driver_ver_version);
1222 printf("\n");
1225 /****************************************************************************
1226 ****************************************************************************/
1228 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1229 TALLOC_CTX *mem_ctx,
1230 int argc, const char **argv)
1232 struct policy_handle pol;
1233 WERROR werror;
1234 uint32_t level = 3;
1235 const char *printername;
1236 uint32_t i;
1237 bool success = false;
1238 union spoolss_DriverInfo info;
1239 uint32_t server_major_version;
1240 uint32_t server_minor_version;
1242 if ((argc == 1) || (argc > 3)) {
1243 printf("Usage: %s <printername> [level]\n", argv[0]);
1244 return WERR_OK;
1247 /* get the arguments need to open the printer handle */
1249 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1251 if (argc == 3) {
1252 level = atoi(argv[2]);
1255 /* Open a printer handle */
1257 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1258 printername,
1259 PRINTER_ACCESS_USE,
1260 &pol);
1261 if (!W_ERROR_IS_OK(werror)) {
1262 printf("Error opening printer handle for %s!\n", printername);
1263 return werror;
1266 /* loop through and print driver info level for each architecture */
1268 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1270 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1271 &pol,
1272 archi_table[i].long_archi,
1273 level,
1274 0, /* offered */
1275 archi_table[i].version,
1277 &info,
1278 &server_major_version,
1279 &server_minor_version);
1280 if (!W_ERROR_IS_OK(werror)) {
1281 continue;
1284 /* need at least one success */
1286 success = true;
1288 printf("\n[%s]\n", archi_table[i].long_archi);
1290 switch (level) {
1291 case 1:
1292 display_print_driver1(&info.info1);
1293 break;
1294 case 2:
1295 display_print_driver2(&info.info2);
1296 break;
1297 case 3:
1298 display_print_driver3(&info.info3);
1299 break;
1300 case 4:
1301 display_print_driver4(&info.info4);
1302 break;
1303 case 5:
1304 display_print_driver5(&info.info5);
1305 break;
1306 case 6:
1307 display_print_driver6(&info.info6);
1308 break;
1309 case 8:
1310 display_print_driver8(&info.info8);
1311 break;
1312 default:
1313 printf("unknown info level %d\n", level);
1314 break;
1318 /* Cleanup */
1320 if (is_valid_policy_hnd(&pol)) {
1321 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1324 if (success) {
1325 werror = WERR_OK;
1328 return werror;
1331 /****************************************************************************
1332 ****************************************************************************/
1334 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1335 TALLOC_CTX *mem_ctx,
1336 const char *architecture,
1337 uint32_t level)
1339 WERROR werror;
1340 uint32_t count = 0;
1341 union spoolss_DriverInfo *info = NULL;
1342 uint32_t j;
1344 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1345 cli->srv_name_slash,
1346 architecture,
1347 level,
1349 &count,
1350 &info);
1352 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1353 printf("Server does not support environment [%s]\n",
1354 architecture);
1355 return WERR_OK;
1358 if (count == 0) {
1359 return WERR_OK;
1362 if (!W_ERROR_IS_OK(werror)) {
1363 printf("Error getting driver for environment [%s] - %s\n",
1364 architecture, win_errstr(werror));
1365 return werror;
1368 printf("\n[%s]\n", architecture);
1370 switch (level) {
1371 case 1:
1372 for (j=0; j < count; j++) {
1373 display_print_driver1(&info[j].info1);
1375 break;
1376 case 2:
1377 for (j=0; j < count; j++) {
1378 display_print_driver2(&info[j].info2);
1380 break;
1381 case 3:
1382 for (j=0; j < count; j++) {
1383 display_print_driver3(&info[j].info3);
1385 break;
1386 case 4:
1387 for (j=0; j < count; j++) {
1388 display_print_driver4(&info[j].info4);
1390 break;
1391 case 5:
1392 for (j=0; j < count; j++) {
1393 display_print_driver5(&info[j].info5);
1395 break;
1396 case 6:
1397 for (j=0; j < count; j++) {
1398 display_print_driver6(&info[j].info6);
1400 break;
1401 case 8:
1402 for (j=0; j < count; j++) {
1403 display_print_driver8(&info[j].info8);
1405 break;
1406 default:
1407 printf("unknown info level %d\n", level);
1408 return WERR_UNKNOWN_LEVEL;
1411 return werror;
1414 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1415 TALLOC_CTX *mem_ctx,
1416 int argc, const char **argv)
1418 WERROR werror = WERR_OK;
1419 uint32_t level = 1;
1420 uint32_t i;
1421 const char *architecture = NULL;
1423 if (argc > 3) {
1424 printf("Usage: enumdrivers [level] [architecture]\n");
1425 return WERR_OK;
1428 if (argc >= 2) {
1429 level = atoi(argv[1]);
1432 if (argc == 3) {
1433 architecture = argv[2];
1436 if (architecture) {
1437 return enum_driver_by_architecture(cli, mem_ctx,
1438 architecture,
1439 level);
1442 /* loop through and print driver info level for each architecture */
1443 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1444 /* check to see if we already asked for this architecture string */
1446 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1447 continue;
1450 werror = enum_driver_by_architecture(cli, mem_ctx,
1451 archi_table[i].long_archi,
1452 level);
1453 if (!W_ERROR_IS_OK(werror)) {
1454 break;
1458 return werror;
1461 /****************************************************************************
1462 ****************************************************************************/
1464 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1466 printf("\tDirectory Name:[%s]\n", r->directory_name);
1469 /****************************************************************************
1470 ****************************************************************************/
1472 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1473 TALLOC_CTX *mem_ctx,
1474 int argc, const char **argv)
1476 WERROR result;
1477 NTSTATUS status;
1478 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1479 DATA_BLOB buffer;
1480 uint32_t offered;
1481 union spoolss_DriverDirectoryInfo info;
1482 uint32_t needed;
1484 if (argc > 2) {
1485 printf("Usage: %s [environment]\n", argv[0]);
1486 return WERR_OK;
1489 /* Get the arguments need to open the printer handle */
1491 if (argc == 2) {
1492 env = argv[1];
1495 /* Get the directory. Only use Info level 1 */
1497 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1498 cli->srv_name_slash,
1499 env,
1501 NULL, /* buffer */
1502 0, /* offered */
1503 NULL, /* info */
1504 &needed,
1505 &result);
1506 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1507 offered = needed;
1508 buffer = data_blob_talloc_zero(mem_ctx, needed);
1510 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1511 cli->srv_name_slash,
1512 env,
1514 &buffer,
1515 offered,
1516 &info,
1517 &needed,
1518 &result);
1521 if (W_ERROR_IS_OK(result)) {
1522 display_printdriverdir_1(&info.info1);
1525 return result;
1528 /****************************************************************************
1529 ****************************************************************************/
1531 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1532 struct spoolss_AddDriverInfo3 *info,
1533 const char *arch)
1536 int i;
1538 for (i=0; archi_table[i].long_archi != NULL; i++)
1540 if (strcmp(arch, archi_table[i].short_archi) == 0)
1542 info->version = archi_table[i].version;
1543 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1544 break;
1548 if (archi_table[i].long_archi == NULL)
1550 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1553 return;
1557 /**************************************************************************
1558 wrapper for strtok to get the next parameter from a delimited list.
1559 Needed to handle the empty parameter string denoted by "NULL"
1560 *************************************************************************/
1562 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1563 const char *delim, const char **dest,
1564 char **saveptr)
1566 char *ptr;
1568 /* get the next token */
1569 ptr = strtok_r(str, delim, saveptr);
1571 /* a string of 'NULL' is used to represent an empty
1572 parameter because two consecutive delimiters
1573 will not return an empty string. See man strtok(3)
1574 for details */
1575 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1576 ptr = NULL;
1579 if (dest != NULL) {
1580 *dest = talloc_strdup(mem_ctx, ptr);
1583 return ptr;
1586 /********************************************************************************
1587 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1588 string in the form of
1589 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1590 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1591 <Default Data Type>:<Comma Separated list of Files>
1592 *******************************************************************************/
1594 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1595 char *args)
1597 char *str, *str2;
1598 int count = 0;
1599 char *saveptr = NULL;
1600 struct spoolss_StringArray *deps;
1601 const char **file_array = NULL;
1602 int i;
1604 /* fill in the UNISTR fields */
1605 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1606 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1607 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1608 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1609 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1610 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1611 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1613 /* <Comma Separated List of Dependent Files> */
1614 /* save the beginning of the string */
1615 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1616 str = str2;
1618 /* begin to strip out each filename */
1619 str = strtok_r(str, ",", &saveptr);
1621 /* no dependent files, we are done */
1622 if (!str) {
1623 return true;
1626 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1627 if (!deps) {
1628 return false;
1631 while (str != NULL) {
1632 add_string_to_array(deps, str, &file_array, &count);
1633 str = strtok_r(NULL, ",", &saveptr);
1636 deps->string = talloc_zero_array(deps, const char *, count + 1);
1637 if (!deps->string) {
1638 return false;
1641 for (i=0; i < count; i++) {
1642 deps->string[i] = file_array[i];
1645 r->dependent_files = deps;
1647 return true;
1650 /****************************************************************************
1651 ****************************************************************************/
1653 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1654 TALLOC_CTX *mem_ctx,
1655 int argc, const char **argv)
1657 WERROR result;
1658 NTSTATUS status;
1659 uint32_t level = 3;
1660 struct spoolss_AddDriverInfoCtr info_ctr;
1661 struct spoolss_AddDriverInfo3 info3;
1662 const char *arch;
1663 char *driver_args;
1665 /* parse the command arguments */
1666 if (argc != 3 && argc != 4)
1668 printf ("Usage: %s <Environment> \\\n", argv[0]);
1669 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1670 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1671 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1672 printf ("\t[version]\n");
1674 return WERR_OK;
1677 /* Fill in the spoolss_AddDriverInfo3 struct */
1678 ZERO_STRUCT(info3);
1680 arch = cmd_spoolss_get_short_archi(argv[1]);
1681 if (!arch) {
1682 printf ("Error Unknown architechture [%s]\n", argv[1]);
1683 return WERR_INVALID_PARAM;
1686 set_drv_info_3_env(mem_ctx, &info3, arch);
1688 driver_args = talloc_strdup( mem_ctx, argv[2] );
1689 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1691 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1692 return WERR_INVALID_PARAM;
1695 /* if printer driver version specified, override the default version
1696 * used by the architecture. This allows installation of Windows
1697 * 2000 (version 3) printer drivers. */
1698 if (argc == 4)
1700 info3.version = atoi(argv[3]);
1704 info_ctr.level = level;
1705 info_ctr.info.info3 = &info3;
1707 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1708 cli->srv_name_slash,
1709 &info_ctr,
1710 &result);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return ntstatus_to_werror(status);
1714 if (W_ERROR_IS_OK(result)) {
1715 printf ("Printer Driver %s successfully installed.\n",
1716 info3.driver_name);
1719 return result;
1723 /****************************************************************************
1724 ****************************************************************************/
1726 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1727 TALLOC_CTX *mem_ctx,
1728 int argc, const char **argv)
1730 WERROR result;
1731 struct spoolss_SetPrinterInfoCtr info_ctr;
1732 struct spoolss_SetPrinterInfo2 info2;
1734 /* parse the command arguments */
1735 if (argc != 5)
1737 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1738 return WERR_OK;
1741 /* Fill in the DRIVER_INFO_2 struct */
1742 ZERO_STRUCT(info2);
1744 info2.printername = argv[1];
1745 info2.drivername = argv[3];
1746 info2.sharename = argv[2];
1747 info2.portname = argv[4];
1748 info2.comment = "Created by rpcclient";
1749 info2.printprocessor = "winprint";
1750 info2.datatype = "RAW";
1751 info2.devmode_ptr = 0;
1752 info2.secdesc_ptr = 0;
1753 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1754 info2.priority = 0;
1755 info2.defaultpriority = 0;
1756 info2.starttime = 0;
1757 info2.untiltime = 0;
1759 /* These three fields must not be used by AddPrinter()
1760 as defined in the MS Platform SDK documentation..
1761 --jerry
1762 info2.status = 0;
1763 info2.cjobs = 0;
1764 info2.averageppm = 0;
1767 info_ctr.level = 2;
1768 info_ctr.info.info2 = &info2;
1770 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1771 &info_ctr);
1772 if (W_ERROR_IS_OK(result))
1773 printf ("Printer %s successfully installed.\n", argv[1]);
1775 return result;
1778 /****************************************************************************
1779 ****************************************************************************/
1781 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1782 TALLOC_CTX *mem_ctx,
1783 int argc, const char **argv)
1785 struct policy_handle pol;
1786 WERROR result;
1787 NTSTATUS status;
1788 uint32_t level = 2;
1789 const char *printername;
1790 union spoolss_PrinterInfo info;
1791 struct spoolss_SetPrinterInfoCtr info_ctr;
1792 struct spoolss_SetPrinterInfo2 info2;
1793 struct spoolss_DevmodeContainer devmode_ctr;
1794 struct sec_desc_buf secdesc_ctr;
1796 ZERO_STRUCT(devmode_ctr);
1797 ZERO_STRUCT(secdesc_ctr);
1799 /* parse the command arguments */
1800 if (argc != 3)
1802 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1803 return WERR_OK;
1806 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1808 /* Get a printer handle */
1810 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1811 printername,
1812 PRINTER_ALL_ACCESS,
1813 &pol);
1814 if (!W_ERROR_IS_OK(result))
1815 goto done;
1817 /* Get printer info */
1819 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1820 &pol,
1821 level,
1823 &info);
1824 if (!W_ERROR_IS_OK(result)) {
1825 printf ("Unable to retrieve printer information!\n");
1826 goto done;
1829 /* Set the printer driver */
1831 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1832 info2.drivername = argv[2];
1834 info_ctr.level = 2;
1835 info_ctr.info.info2 = &info2;
1837 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1838 &pol,
1839 &info_ctr,
1840 &devmode_ctr,
1841 &secdesc_ctr,
1842 0, /* command */
1843 &result);
1844 if (!W_ERROR_IS_OK(result)) {
1845 printf("SetPrinter call failed!\n");
1846 goto done;;
1849 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1851 done:
1852 /* Cleanup */
1854 if (is_valid_policy_hnd(&pol))
1855 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1857 return result;
1861 /****************************************************************************
1862 ****************************************************************************/
1864 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1865 TALLOC_CTX *mem_ctx,
1866 int argc, const char **argv)
1868 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1869 NTSTATUS status;
1871 int i;
1872 int vers = -1;
1874 const char *arch = NULL;
1875 uint32_t delete_flags = 0;
1877 /* parse the command arguments */
1878 if (argc < 2 || argc > 4) {
1879 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1880 return WERR_OK;
1883 if (argc >= 3)
1884 arch = argv[2];
1885 if (argc == 4)
1886 vers = atoi (argv[3]);
1888 if (vers >= 0) {
1889 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1892 /* delete the driver for all architectures */
1893 for (i=0; archi_table[i].long_archi; i++) {
1895 if (arch && !strequal( archi_table[i].long_archi, arch))
1896 continue;
1898 if (vers >= 0 && archi_table[i].version != vers)
1899 continue;
1901 /* make the call to remove the driver */
1902 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1903 cli->srv_name_slash,
1904 archi_table[i].long_archi,
1905 argv[1],
1906 delete_flags,
1907 archi_table[i].version,
1908 &result);
1910 if ( !W_ERROR_IS_OK(result) )
1912 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1913 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1914 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1917 else
1919 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1920 archi_table[i].long_archi, archi_table[i].version);
1921 ret = WERR_OK;
1925 return ret;
1929 /****************************************************************************
1930 ****************************************************************************/
1932 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1933 TALLOC_CTX *mem_ctx,
1934 int argc, const char **argv)
1936 WERROR result = WERR_OK;
1937 NTSTATUS status;
1938 int i;
1940 /* parse the command arguments */
1941 if (argc != 2) {
1942 printf ("Usage: %s <driver>\n", argv[0]);
1943 return WERR_OK;
1946 /* delete the driver for all architectures */
1947 for (i=0; archi_table[i].long_archi; i++) {
1948 result = WERR_OK;
1950 /* make the call to remove the driver */
1951 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1952 cli->srv_name_slash,
1953 archi_table[i].long_archi,
1954 argv[1],
1955 &result);
1956 if (!NT_STATUS_IS_OK(status)) {
1957 if (W_ERROR_IS_OK(result)) {
1958 result = ntstatus_to_werror(status);
1961 if ( !W_ERROR_IS_OK(result) ) {
1962 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1963 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1964 argv[1], archi_table[i].long_archi,
1965 W_ERROR_V(result));
1967 } else {
1968 printf ("Driver %s removed for arch [%s].\n", argv[1],
1969 archi_table[i].long_archi);
1973 return result;
1976 /****************************************************************************
1977 ****************************************************************************/
1979 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1980 TALLOC_CTX *mem_ctx,
1981 int argc, const char **argv)
1983 WERROR result;
1984 NTSTATUS status;
1985 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1986 DATA_BLOB buffer;
1987 uint32_t offered;
1988 union spoolss_PrintProcessorDirectoryInfo info;
1989 uint32_t needed;
1991 /* parse the command arguments */
1992 if (argc > 2) {
1993 printf ("Usage: %s [environment]\n", argv[0]);
1994 return WERR_OK;
1997 if (argc == 2) {
1998 environment = argv[1];
2001 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2002 cli->srv_name_slash,
2003 environment,
2005 NULL, /* buffer */
2006 0, /* offered */
2007 NULL, /* info */
2008 &needed,
2009 &result);
2010 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2011 offered = needed;
2012 buffer = data_blob_talloc_zero(mem_ctx, needed);
2014 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2015 cli->srv_name_slash,
2016 environment,
2018 &buffer,
2019 offered,
2020 &info,
2021 &needed,
2022 &result);
2025 if (W_ERROR_IS_OK(result)) {
2026 printf("%s\n", info.info1.directory_name);
2029 return result;
2032 /****************************************************************************
2033 ****************************************************************************/
2035 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2036 int argc, const char **argv)
2038 struct policy_handle handle;
2039 WERROR werror;
2040 NTSTATUS status;
2041 const char *printername;
2042 union spoolss_AddFormInfo info;
2043 struct spoolss_AddFormInfo1 info1;
2044 struct spoolss_AddFormInfo2 info2;
2045 uint32_t level = 1;
2047 /* Parse the command arguments */
2049 if (argc < 3 || argc > 5) {
2050 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2051 return WERR_OK;
2054 /* Get a printer handle */
2056 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2058 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2059 printername,
2060 PRINTER_ALL_ACCESS,
2061 &handle);
2062 if (!W_ERROR_IS_OK(werror))
2063 goto done;
2065 /* Dummy up some values for the form data */
2067 if (argc == 4) {
2068 level = atoi(argv[3]);
2071 switch (level) {
2072 case 1:
2073 info1.flags = SPOOLSS_FORM_USER;
2074 info1.form_name = argv[2];
2075 info1.size.width = 100;
2076 info1.size.height = 100;
2077 info1.area.left = 0;
2078 info1.area.top = 10;
2079 info1.area.right = 20;
2080 info1.area.bottom = 30;
2082 info.info1 = &info1;
2084 break;
2085 case 2:
2086 info2.flags = SPOOLSS_FORM_USER;
2087 info2.form_name = argv[2];
2088 info2.size.width = 100;
2089 info2.size.height = 100;
2090 info2.area.left = 0;
2091 info2.area.top = 10;
2092 info2.area.right = 20;
2093 info2.area.bottom = 30;
2094 info2.keyword = argv[2];
2095 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2096 info2.mui_dll = NULL;
2097 info2.ressource_id = 0;
2098 info2.display_name = argv[2];
2099 info2.lang_id = 0;
2101 info.info2 = &info2;
2103 break;
2106 /* Add the form */
2109 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2110 &handle,
2111 level,
2112 info,
2113 &werror);
2115 done:
2116 if (is_valid_policy_hnd(&handle))
2117 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2119 return werror;
2122 /****************************************************************************
2123 ****************************************************************************/
2125 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2126 int argc, const char **argv)
2128 struct policy_handle handle;
2129 WERROR werror;
2130 NTSTATUS status;
2131 const char *printername;
2132 union spoolss_AddFormInfo info;
2133 struct spoolss_AddFormInfo1 info1;
2135 /* Parse the command arguments */
2137 if (argc != 3) {
2138 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2139 return WERR_OK;
2142 /* Get a printer handle */
2144 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2146 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2147 printername,
2148 SEC_FLAG_MAXIMUM_ALLOWED,
2149 &handle);
2150 if (!W_ERROR_IS_OK(werror))
2151 goto done;
2153 /* Dummy up some values for the form data */
2155 info1.flags = SPOOLSS_FORM_PRINTER;
2156 info1.size.width = 100;
2157 info1.size.height = 100;
2158 info1.area.left = 0;
2159 info1.area.top = 1000;
2160 info1.area.right = 2000;
2161 info1.area.bottom = 3000;
2162 info1.form_name = argv[2];
2164 info.info1 = &info1;
2166 /* Set the form */
2168 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2169 &handle,
2170 argv[2],
2172 info,
2173 &werror);
2175 done:
2176 if (is_valid_policy_hnd(&handle))
2177 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2179 return werror;
2182 /****************************************************************************
2183 ****************************************************************************/
2185 static const char *get_form_flag(int form_flag)
2187 switch (form_flag) {
2188 case SPOOLSS_FORM_USER:
2189 return "FORM_USER";
2190 case SPOOLSS_FORM_BUILTIN:
2191 return "FORM_BUILTIN";
2192 case SPOOLSS_FORM_PRINTER:
2193 return "FORM_PRINTER";
2194 default:
2195 return "unknown";
2199 /****************************************************************************
2200 ****************************************************************************/
2202 static void display_form_info1(struct spoolss_FormInfo1 *r)
2204 printf("%s\n" \
2205 "\tflag: %s (%d)\n" \
2206 "\twidth: %d, length: %d\n" \
2207 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2208 r->form_name, get_form_flag(r->flags), r->flags,
2209 r->size.width, r->size.height,
2210 r->area.left, r->area.right,
2211 r->area.top, r->area.bottom);
2214 /****************************************************************************
2215 ****************************************************************************/
2217 static void display_form_info2(struct spoolss_FormInfo2 *r)
2219 printf("%s\n" \
2220 "\tflag: %s (%d)\n" \
2221 "\twidth: %d, length: %d\n" \
2222 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2223 r->form_name, get_form_flag(r->flags), r->flags,
2224 r->size.width, r->size.height,
2225 r->area.left, r->area.right,
2226 r->area.top, r->area.bottom);
2227 printf("\tkeyword: %s\n", r->keyword);
2228 printf("\tstring_type: 0x%08x\n", r->string_type);
2229 printf("\tmui_dll: %s\n", r->mui_dll);
2230 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2231 printf("\tdisplay_name: %s\n", r->display_name);
2232 printf("\tlang_id: %d\n", r->lang_id);
2233 printf("\n");
2236 /****************************************************************************
2237 ****************************************************************************/
2239 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2240 int argc, const char **argv)
2242 struct policy_handle handle;
2243 WERROR werror;
2244 NTSTATUS status;
2245 const char *printername;
2246 DATA_BLOB buffer;
2247 uint32_t offered = 0;
2248 union spoolss_FormInfo info;
2249 uint32_t needed;
2250 uint32_t level = 1;
2252 /* Parse the command arguments */
2254 if (argc < 3 || argc > 5) {
2255 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2256 return WERR_OK;
2259 /* Get a printer handle */
2261 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2263 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2264 printername,
2265 SEC_FLAG_MAXIMUM_ALLOWED,
2266 &handle);
2267 if (!W_ERROR_IS_OK(werror))
2268 goto done;
2270 if (argc == 4) {
2271 level = atoi(argv[3]);
2274 /* Get the form */
2276 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2277 &handle,
2278 argv[2],
2279 level,
2280 NULL,
2281 offered,
2282 &info,
2283 &needed,
2284 &werror);
2285 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2286 buffer = data_blob_talloc_zero(mem_ctx, needed);
2287 offered = needed;
2288 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2289 &handle,
2290 argv[2],
2291 level,
2292 &buffer,
2293 offered,
2294 &info,
2295 &needed,
2296 &werror);
2299 if (!NT_STATUS_IS_OK(status)) {
2300 return werror;
2303 switch (level) {
2304 case 1:
2305 display_form_info1(&info.info1);
2306 break;
2307 case 2:
2308 display_form_info2(&info.info2);
2309 break;
2312 done:
2313 if (is_valid_policy_hnd(&handle))
2314 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2316 return werror;
2319 /****************************************************************************
2320 ****************************************************************************/
2322 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2323 TALLOC_CTX *mem_ctx, int argc,
2324 const char **argv)
2326 struct policy_handle handle;
2327 WERROR werror;
2328 NTSTATUS status;
2329 const char *printername;
2331 /* Parse the command arguments */
2333 if (argc != 3) {
2334 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2335 return WERR_OK;
2338 /* Get a printer handle */
2340 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2342 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2343 printername,
2344 SEC_FLAG_MAXIMUM_ALLOWED,
2345 &handle);
2346 if (!W_ERROR_IS_OK(werror))
2347 goto done;
2349 /* Delete the form */
2351 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2352 &handle,
2353 argv[2],
2354 &werror);
2355 if (!NT_STATUS_IS_OK(status)) {
2356 return ntstatus_to_werror(status);
2359 done:
2360 if (is_valid_policy_hnd(&handle))
2361 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2363 return werror;
2366 /****************************************************************************
2367 ****************************************************************************/
2369 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2370 TALLOC_CTX *mem_ctx, int argc,
2371 const char **argv)
2373 struct policy_handle handle;
2374 WERROR werror;
2375 const char *printername;
2376 uint32_t num_forms, level = 1, i;
2377 union spoolss_FormInfo *forms;
2379 /* Parse the command arguments */
2381 if (argc < 2 || argc > 4) {
2382 printf ("Usage: %s <printer> [level]\n", argv[0]);
2383 return WERR_OK;
2386 /* Get a printer handle */
2388 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2390 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2391 printername,
2392 SEC_FLAG_MAXIMUM_ALLOWED,
2393 &handle);
2394 if (!W_ERROR_IS_OK(werror))
2395 goto done;
2397 if (argc == 3) {
2398 level = atoi(argv[2]);
2401 /* Enumerate forms */
2403 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2404 &handle,
2405 level,
2407 &num_forms,
2408 &forms);
2410 if (!W_ERROR_IS_OK(werror))
2411 goto done;
2413 /* Display output */
2415 for (i = 0; i < num_forms; i++) {
2416 switch (level) {
2417 case 1:
2418 display_form_info1(&forms[i].info1);
2419 break;
2420 case 2:
2421 display_form_info2(&forms[i].info2);
2422 break;
2426 done:
2427 if (is_valid_policy_hnd(&handle))
2428 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2430 return werror;
2433 /****************************************************************************
2434 ****************************************************************************/
2436 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2437 TALLOC_CTX *mem_ctx,
2438 int argc, const char **argv)
2440 WERROR result;
2441 NTSTATUS status;
2442 const char *printername;
2443 struct policy_handle pol;
2444 union spoolss_PrinterInfo info;
2445 enum winreg_Type type;
2446 union spoolss_PrinterData data;
2447 DATA_BLOB blob;
2449 /* parse the command arguments */
2450 if (argc < 5) {
2451 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2452 " <value> <data>\n",
2453 argv[0]);
2454 return WERR_OK;
2457 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2459 type = REG_NONE;
2461 if (strequal(argv[2], "string")) {
2462 type = REG_SZ;
2465 if (strequal(argv[2], "binary")) {
2466 type = REG_BINARY;
2469 if (strequal(argv[2], "dword")) {
2470 type = REG_DWORD;
2473 if (strequal(argv[2], "multistring")) {
2474 type = REG_MULTI_SZ;
2477 if (type == REG_NONE) {
2478 printf("Unknown data type: %s\n", argv[2]);
2479 result = WERR_INVALID_PARAM;
2480 goto done;
2483 /* get a printer handle */
2485 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2486 printername,
2487 SEC_FLAG_MAXIMUM_ALLOWED,
2488 &pol);
2489 if (!W_ERROR_IS_OK(result)) {
2490 goto done;
2493 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2494 &pol,
2497 &info);
2498 if (!W_ERROR_IS_OK(result)) {
2499 goto done;
2502 printf("%s\n", current_timestring(mem_ctx, true));
2503 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2505 /* Set the printer data */
2507 switch (type) {
2508 case REG_SZ:
2509 data.string = talloc_strdup(mem_ctx, argv[4]);
2510 W_ERROR_HAVE_NO_MEMORY(data.string);
2511 break;
2512 case REG_DWORD:
2513 data.value = strtoul(argv[4], NULL, 10);
2514 break;
2515 case REG_BINARY:
2516 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2517 break;
2518 case REG_MULTI_SZ: {
2519 int i, num_strings;
2520 const char **strings = NULL;
2522 for (i=4; i<argc; i++) {
2523 if (strcmp(argv[i], "NULL") == 0) {
2524 argv[i] = "";
2526 if (!add_string_to_array(mem_ctx, argv[i],
2527 &strings,
2528 &num_strings)) {
2529 result = WERR_NOMEM;
2530 goto done;
2533 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2534 if (!data.string_array) {
2535 result = WERR_NOMEM;
2536 goto done;
2538 for (i=0; i < num_strings; i++) {
2539 data.string_array[i] = strings[i];
2541 break;
2543 default:
2544 printf("Unknown data type: %s\n", argv[2]);
2545 result = WERR_INVALID_PARAM;
2546 goto done;
2549 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2550 if (!W_ERROR_IS_OK(result)) {
2551 goto done;
2554 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2555 &pol,
2556 argv[3], /* value_name */
2557 type,
2558 blob.data,
2559 blob.length,
2560 &result);
2561 if (!W_ERROR_IS_OK(result)) {
2562 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2563 goto done;
2565 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2567 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2568 &pol,
2571 &info);
2572 if (!W_ERROR_IS_OK(result)) {
2573 goto done;
2576 printf("%s\n", current_timestring(mem_ctx, true));
2577 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2579 done:
2580 /* cleanup */
2581 if (is_valid_policy_hnd(&pol)) {
2582 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2585 return result;
2588 /****************************************************************************
2589 ****************************************************************************/
2591 static void display_job_info1(struct spoolss_JobInfo1 *r)
2593 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2594 r->user_name, r->document_name, r->text_status, r->pages_printed,
2595 r->total_pages);
2598 /****************************************************************************
2599 ****************************************************************************/
2601 static void display_job_info2(struct spoolss_JobInfo2 *r)
2603 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2604 r->position, r->job_id,
2605 r->user_name, r->document_name, r->text_status, r->pages_printed,
2606 r->total_pages, r->size);
2609 /****************************************************************************
2610 ****************************************************************************/
2612 static void display_job_info3(struct spoolss_JobInfo3 *r)
2614 printf("jobid[%d], next_jobid[%d]\n",
2615 r->job_id, r->next_job_id);
2618 /****************************************************************************
2619 ****************************************************************************/
2621 static void display_job_info4(struct spoolss_JobInfo4 *r)
2623 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2624 r->position, r->job_id,
2625 r->user_name, r->document_name, r->text_status, r->pages_printed,
2626 r->total_pages, r->size, r->size_high);
2629 /****************************************************************************
2630 ****************************************************************************/
2632 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2633 TALLOC_CTX *mem_ctx, int argc,
2634 const char **argv)
2636 WERROR result;
2637 uint32_t level = 1, count, i;
2638 const char *printername;
2639 struct policy_handle hnd;
2640 union spoolss_JobInfo *info;
2642 if (argc < 2 || argc > 3) {
2643 printf("Usage: %s printername [level]\n", argv[0]);
2644 return WERR_OK;
2647 if (argc == 3) {
2648 level = atoi(argv[2]);
2651 /* Open printer handle */
2653 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2655 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2656 printername,
2657 SEC_FLAG_MAXIMUM_ALLOWED,
2658 &hnd);
2659 if (!W_ERROR_IS_OK(result))
2660 goto done;
2662 /* Enumerate ports */
2664 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2665 &hnd,
2666 0, /* firstjob */
2667 1000, /* numjobs */
2668 level,
2670 &count,
2671 &info);
2672 if (!W_ERROR_IS_OK(result)) {
2673 goto done;
2676 for (i = 0; i < count; i++) {
2677 switch (level) {
2678 case 1:
2679 display_job_info1(&info[i].info1);
2680 break;
2681 case 2:
2682 display_job_info2(&info[i].info2);
2683 break;
2684 default:
2685 d_printf("unknown info level %d\n", level);
2686 break;
2690 done:
2691 if (is_valid_policy_hnd(&hnd)) {
2692 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2695 return result;
2698 /****************************************************************************
2699 ****************************************************************************/
2701 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2702 TALLOC_CTX *mem_ctx, int argc,
2703 const char **argv)
2705 WERROR result;
2706 const char *printername;
2707 struct policy_handle hnd;
2708 uint32_t job_id;
2709 uint32_t level = 1;
2710 union spoolss_JobInfo info;
2712 if (argc < 3 || argc > 4) {
2713 printf("Usage: %s printername job_id [level]\n", argv[0]);
2714 return WERR_OK;
2717 job_id = atoi(argv[2]);
2719 if (argc == 4) {
2720 level = atoi(argv[3]);
2723 /* Open printer handle */
2725 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2727 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2728 printername,
2729 SEC_FLAG_MAXIMUM_ALLOWED,
2730 &hnd);
2731 if (!W_ERROR_IS_OK(result)) {
2732 goto done;
2735 /* Enumerate ports */
2737 result = rpccli_spoolss_getjob(cli, mem_ctx,
2738 &hnd,
2739 job_id,
2740 level,
2742 &info);
2744 if (!W_ERROR_IS_OK(result)) {
2745 goto done;
2748 switch (level) {
2749 case 1:
2750 display_job_info1(&info.info1);
2751 break;
2752 case 2:
2753 display_job_info2(&info.info2);
2754 break;
2755 case 3:
2756 display_job_info3(&info.info3);
2757 break;
2758 case 4:
2759 display_job_info4(&info.info4);
2760 break;
2761 default:
2762 d_printf("unknown info level %d\n", level);
2763 break;
2766 done:
2767 if (is_valid_policy_hnd(&hnd)) {
2768 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2771 return result;
2774 /****************************************************************************
2775 ****************************************************************************/
2777 static struct {
2778 const char *name;
2779 enum spoolss_JobControl val;
2780 } cmdvals[] = {
2781 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2782 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2783 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2784 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2785 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2786 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2787 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2788 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2789 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2792 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2794 int i;
2796 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2797 if (strequal(cmdvals[i].name, cmd)) {
2798 return cmdvals[i].val;
2801 return (enum spoolss_JobControl)atoi(cmd);
2804 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2805 TALLOC_CTX *mem_ctx, int argc,
2806 const char **argv)
2808 WERROR result;
2809 NTSTATUS status;
2810 const char *printername;
2811 struct policy_handle hnd;
2812 uint32_t job_id;
2813 enum spoolss_JobControl command;
2815 if (argc != 4) {
2816 printf("Usage: %s printername job_id command\n", argv[0]);
2817 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2818 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2819 return WERR_OK;
2822 job_id = atoi(argv[2]);
2823 command = parse_setjob_command(argv[3]);
2825 /* Open printer handle */
2827 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2829 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2830 printername,
2831 SEC_FLAG_MAXIMUM_ALLOWED,
2832 &hnd);
2833 if (!W_ERROR_IS_OK(result)) {
2834 goto done;
2837 /* Set Job */
2839 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2840 &hnd,
2841 job_id,
2842 NULL,
2843 command,
2844 &result);
2846 if (!W_ERROR_IS_OK(result)) {
2847 goto done;
2850 done:
2851 if (is_valid_policy_hnd(&hnd)) {
2852 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2855 return result;
2858 /****************************************************************************
2859 ****************************************************************************/
2861 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2862 TALLOC_CTX *mem_ctx, int argc,
2863 const char **argv)
2865 WERROR result;
2866 NTSTATUS status;
2867 uint32_t i = 0;
2868 const char *printername;
2869 struct policy_handle hnd;
2870 uint32_t value_offered = 0;
2871 const char *value_name = NULL;
2872 uint32_t value_needed;
2873 enum winreg_Type type;
2874 uint8_t *data = NULL;
2875 uint32_t data_offered = 0;
2876 uint32_t data_needed;
2878 if (argc != 2) {
2879 printf("Usage: %s printername\n", argv[0]);
2880 return WERR_OK;
2883 /* Open printer handle */
2885 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2887 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2888 printername,
2889 SEC_FLAG_MAXIMUM_ALLOWED,
2890 &hnd);
2891 if (!W_ERROR_IS_OK(result)) {
2892 goto done;
2895 /* Enumerate data */
2897 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2898 &hnd,
2900 value_name,
2901 value_offered,
2902 &value_needed,
2903 &type,
2904 data,
2905 data_offered,
2906 &data_needed,
2907 &result);
2909 if (!NT_STATUS_IS_OK(status)) {
2910 result = ntstatus_to_werror(status);
2911 goto done;
2914 if (!W_ERROR_IS_OK(result)) {
2915 goto done;
2918 data_offered = data_needed;
2919 value_offered = value_needed;
2920 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2921 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2923 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2925 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2926 &hnd,
2927 i++,
2928 value_name,
2929 value_offered,
2930 &value_needed,
2931 &type,
2932 data,
2933 data_offered,
2934 &data_needed,
2935 &result);
2936 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2937 struct regval_blob *v;
2939 v = regval_compose(talloc_tos(),
2940 value_name,
2941 type,
2942 data,
2943 data_offered);
2944 if (v == NULL) {
2945 result = WERR_NOMEM;
2946 goto done;
2949 display_reg_value(v);
2950 talloc_free(v);
2954 if (W_ERROR_V(result) == ERRnomoreitems) {
2955 result = W_ERROR(ERRsuccess);
2958 done:
2959 if (is_valid_policy_hnd(&hnd)) {
2960 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2963 return result;
2966 /****************************************************************************
2967 ****************************************************************************/
2969 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2970 TALLOC_CTX *mem_ctx, int argc,
2971 const char **argv)
2973 WERROR result;
2974 uint32_t i;
2975 const char *printername;
2976 struct policy_handle hnd;
2977 uint32_t count;
2978 struct spoolss_PrinterEnumValues *info;
2980 if (argc != 3) {
2981 printf("Usage: %s printername <keyname>\n", argv[0]);
2982 return WERR_OK;
2985 /* Open printer handle */
2987 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2989 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2990 printername,
2991 SEC_FLAG_MAXIMUM_ALLOWED,
2992 &hnd);
2993 if (!W_ERROR_IS_OK(result)) {
2994 goto done;
2997 /* Enumerate subkeys */
2999 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3000 &hnd,
3001 argv[2],
3003 &count,
3004 &info);
3005 if (!W_ERROR_IS_OK(result)) {
3006 goto done;
3009 for (i=0; i < count; i++) {
3010 display_printer_data(info[i].value_name,
3011 info[i].type,
3012 info[i].data->data,
3013 info[i].data->length);
3016 done:
3017 if (is_valid_policy_hnd(&hnd)) {
3018 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3021 return result;
3024 /****************************************************************************
3025 ****************************************************************************/
3027 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3028 TALLOC_CTX *mem_ctx, int argc,
3029 const char **argv)
3031 WERROR result;
3032 const char *printername;
3033 const char *keyname = NULL;
3034 struct policy_handle hnd;
3035 const char **key_buffer = NULL;
3036 int i;
3037 uint32_t offered = 0;
3039 if (argc < 2 || argc > 4) {
3040 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3041 return WERR_OK;
3044 if (argc >= 3) {
3045 keyname = argv[2];
3046 } else {
3047 keyname = "";
3050 if (argc == 4) {
3051 offered = atoi(argv[3]);
3054 /* Open printer handle */
3056 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3058 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3059 printername,
3060 SEC_FLAG_MAXIMUM_ALLOWED,
3061 &hnd);
3062 if (!W_ERROR_IS_OK(result)) {
3063 goto done;
3066 /* Enumerate subkeys */
3068 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3069 &hnd,
3070 keyname,
3071 &key_buffer,
3072 offered);
3074 if (!W_ERROR_IS_OK(result)) {
3075 goto done;
3078 for (i=0; key_buffer && key_buffer[i]; i++) {
3079 printf("%s\n", key_buffer[i]);
3082 done:
3084 if (is_valid_policy_hnd(&hnd)) {
3085 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3088 return result;
3091 /****************************************************************************
3092 ****************************************************************************/
3094 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3095 TALLOC_CTX *mem_ctx, int argc,
3096 const char **argv)
3098 const char *printername;
3099 const char *clientname;
3100 struct policy_handle hnd;
3101 WERROR result;
3102 NTSTATUS status;
3103 struct spoolss_NotifyOption option;
3105 if (argc != 2) {
3106 printf("Usage: %s printername\n", argv[0]);
3107 result = WERR_OK;
3108 goto done;
3111 /* Open printer */
3113 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3115 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3116 printername,
3117 SEC_FLAG_MAXIMUM_ALLOWED,
3118 &hnd);
3119 if (!W_ERROR_IS_OK(result)) {
3120 printf("Error opening %s\n", argv[1]);
3121 goto done;
3124 /* Create spool options */
3126 option.version = 2;
3127 option.count = 2;
3129 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3130 if (option.types == NULL) {
3131 result = WERR_NOMEM;
3132 goto done;
3135 option.types[0].type = PRINTER_NOTIFY_TYPE;
3136 option.types[0].count = 1;
3137 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3138 if (option.types[0].fields == NULL) {
3139 result = WERR_NOMEM;
3140 goto done;
3142 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3144 option.types[1].type = JOB_NOTIFY_TYPE;
3145 option.types[1].count = 1;
3146 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3147 if (option.types[1].fields == NULL) {
3148 result = WERR_NOMEM;
3149 goto done;
3151 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3153 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3154 if (!clientname) {
3155 result = WERR_NOMEM;
3156 goto done;
3159 /* Send rffpcnex */
3161 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3162 &hnd,
3165 clientname,
3166 123,
3167 &option,
3168 &result);
3169 if (!W_ERROR_IS_OK(result)) {
3170 printf("Error rffpcnex %s\n", argv[1]);
3171 goto done;
3174 done:
3175 if (is_valid_policy_hnd(&hnd))
3176 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3178 return result;
3181 /****************************************************************************
3182 ****************************************************************************/
3184 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3185 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3187 union spoolss_PrinterInfo info1, info2;
3188 WERROR werror;
3189 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3191 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3192 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3193 hnd1,
3196 &info1);
3197 if ( !W_ERROR_IS_OK(werror) ) {
3198 printf("failed (%s)\n", win_errstr(werror));
3199 talloc_destroy(mem_ctx);
3200 return false;
3202 printf("ok\n");
3204 printf("Retrieving printer properties for %s...", cli2->desthost);
3205 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3206 hnd2,
3209 &info2);
3210 if ( !W_ERROR_IS_OK(werror) ) {
3211 printf("failed (%s)\n", win_errstr(werror));
3212 talloc_destroy(mem_ctx);
3213 return false;
3215 printf("ok\n");
3217 talloc_destroy(mem_ctx);
3219 return true;
3222 /****************************************************************************
3223 ****************************************************************************/
3225 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3226 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3228 union spoolss_PrinterInfo info1, info2;
3229 WERROR werror;
3230 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3231 struct security_descriptor *sd1, *sd2;
3232 bool result = true;
3235 printf("Retrieving printer security for %s...", cli1->desthost);
3236 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3237 hnd1,
3240 &info1);
3241 if ( !W_ERROR_IS_OK(werror) ) {
3242 printf("failed (%s)\n", win_errstr(werror));
3243 result = false;
3244 goto done;
3246 printf("ok\n");
3248 printf("Retrieving printer security for %s...", cli2->desthost);
3249 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3250 hnd2,
3253 &info2);
3254 if ( !W_ERROR_IS_OK(werror) ) {
3255 printf("failed (%s)\n", win_errstr(werror));
3256 result = false;
3257 goto done;
3259 printf("ok\n");
3262 printf("++ ");
3264 sd1 = info1.info3.secdesc;
3265 sd2 = info2.info3.secdesc;
3267 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3268 printf("NULL secdesc!\n");
3269 result = false;
3270 goto done;
3273 if (!security_descriptor_equal( sd1, sd2 ) ) {
3274 printf("Security Descriptors *not* equal!\n");
3275 result = false;
3276 goto done;
3279 printf("Security descriptors match\n");
3281 done:
3282 talloc_destroy(mem_ctx);
3283 return result;
3287 /****************************************************************************
3288 ****************************************************************************/
3290 extern struct user_auth_info *rpcclient_auth_info;
3292 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3293 TALLOC_CTX *mem_ctx, int argc,
3294 const char **argv)
3296 const char *printername;
3297 char *printername_path = NULL;
3298 struct cli_state *cli_server2 = NULL;
3299 struct rpc_pipe_client *cli2 = NULL;
3300 struct policy_handle hPrinter1, hPrinter2;
3301 NTSTATUS nt_status;
3302 WERROR werror;
3304 if ( argc != 3 ) {
3305 printf("Usage: %s <printer> <server>\n", argv[0]);
3306 return WERR_OK;
3309 printername = argv[1];
3311 /* first get the connection to the remote server */
3313 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3314 NULL, 0,
3315 "IPC$", "IPC",
3316 get_cmdline_auth_info_username(rpcclient_auth_info),
3317 lp_workgroup(),
3318 get_cmdline_auth_info_password(rpcclient_auth_info),
3319 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3320 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3322 if ( !NT_STATUS_IS_OK(nt_status) )
3323 return WERR_GENERAL_FAILURE;
3325 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3326 &cli2);
3327 if (!NT_STATUS_IS_OK(nt_status)) {
3328 printf("failed to open spoolss pipe on server %s (%s)\n",
3329 argv[2], nt_errstr(nt_status));
3330 return WERR_GENERAL_FAILURE;
3333 /* now open up both printers */
3335 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3337 printf("Opening %s...", printername_path);
3339 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3340 printername_path,
3341 PRINTER_ALL_ACCESS,
3342 &hPrinter1);
3343 if ( !W_ERROR_IS_OK(werror) ) {
3344 printf("failed (%s)\n", win_errstr(werror));
3345 goto done;
3347 printf("ok\n");
3349 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3351 printf("Opening %s...", printername_path);
3352 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3353 printername_path,
3354 PRINTER_ALL_ACCESS,
3355 &hPrinter2);
3356 if ( !W_ERROR_IS_OK(werror) ) {
3357 printf("failed (%s)\n", win_errstr(werror));
3358 goto done;
3360 printf("ok\n");
3362 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3363 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3364 #if 0
3365 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3366 #endif
3369 done:
3370 /* cleanup */
3372 printf("Closing printers...");
3373 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3374 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3375 printf("ok\n");
3377 /* close the second remote connection */
3379 cli_shutdown( cli_server2 );
3380 return WERR_OK;
3383 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3385 printf("print_processor_name: %s\n", r->print_processor_name);
3388 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3389 TALLOC_CTX *mem_ctx, int argc,
3390 const char **argv)
3392 WERROR werror;
3393 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3394 uint32_t num_procs, level = 1, i;
3395 union spoolss_PrintProcessorInfo *procs;
3397 /* Parse the command arguments */
3399 if (argc < 1 || argc > 4) {
3400 printf ("Usage: %s [environment] [level]\n", argv[0]);
3401 return WERR_OK;
3404 if (argc >= 2) {
3405 environment = argv[1];
3408 if (argc == 3) {
3409 level = atoi(argv[2]);
3412 /* Enumerate Print Processors */
3414 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3415 cli->srv_name_slash,
3416 environment,
3417 level,
3419 &num_procs,
3420 &procs);
3421 if (!W_ERROR_IS_OK(werror))
3422 goto done;
3424 /* Display output */
3426 for (i = 0; i < num_procs; i++) {
3427 switch (level) {
3428 case 1:
3429 display_proc_info1(&procs[i].info1);
3430 break;
3434 done:
3435 return werror;
3438 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3440 printf("name_array: %s\n", r->name_array);
3443 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3444 TALLOC_CTX *mem_ctx, int argc,
3445 const char **argv)
3447 WERROR werror;
3448 const char *print_processor_name = "winprint";
3449 uint32_t num_procs, level = 1, i;
3450 union spoolss_PrintProcDataTypesInfo *procs;
3452 /* Parse the command arguments */
3454 if (argc < 1 || argc > 4) {
3455 printf ("Usage: %s [environment] [level]\n", argv[0]);
3456 return WERR_OK;
3459 if (argc >= 2) {
3460 print_processor_name = argv[1];
3463 if (argc == 3) {
3464 level = atoi(argv[2]);
3467 /* Enumerate Print Processor Data Types */
3469 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3470 cli->srv_name_slash,
3471 print_processor_name,
3472 level,
3474 &num_procs,
3475 &procs);
3476 if (!W_ERROR_IS_OK(werror))
3477 goto done;
3479 /* Display output */
3481 for (i = 0; i < num_procs; i++) {
3482 switch (level) {
3483 case 1:
3484 display_proc_data_types_info1(&procs[i].info1);
3485 break;
3489 done:
3490 return werror;
3493 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3495 printf("monitor_name: %s\n", r->monitor_name);
3498 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3500 printf("monitor_name: %s\n", r->monitor_name);
3501 printf("environment: %s\n", r->environment);
3502 printf("dll_name: %s\n", r->dll_name);
3505 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3506 TALLOC_CTX *mem_ctx, int argc,
3507 const char **argv)
3509 WERROR werror;
3510 uint32_t count, level = 1, i;
3511 union spoolss_MonitorInfo *info;
3513 /* Parse the command arguments */
3515 if (argc > 2) {
3516 printf("Usage: %s [level]\n", argv[0]);
3517 return WERR_OK;
3520 if (argc == 2) {
3521 level = atoi(argv[1]);
3524 /* Enumerate Print Monitors */
3526 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3527 cli->srv_name_slash,
3528 level,
3530 &count,
3531 &info);
3532 if (!W_ERROR_IS_OK(werror)) {
3533 goto done;
3536 /* Display output */
3538 for (i = 0; i < count; i++) {
3539 switch (level) {
3540 case 1:
3541 display_monitor1(&info[i].info1);
3542 break;
3543 case 2:
3544 display_monitor2(&info[i].info2);
3545 break;
3549 done:
3550 return werror;
3553 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3554 TALLOC_CTX *mem_ctx, int argc,
3555 const char **argv)
3557 WERROR result;
3558 NTSTATUS status;
3559 struct policy_handle handle, gdi_handle;
3560 const char *printername;
3561 struct spoolss_DevmodeContainer devmode_ctr;
3563 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3565 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3566 printername,
3567 SEC_FLAG_MAXIMUM_ALLOWED,
3568 &handle);
3569 if (!W_ERROR_IS_OK(result)) {
3570 return result;
3573 ZERO_STRUCT(devmode_ctr);
3575 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3576 &handle,
3577 &gdi_handle,
3578 &devmode_ctr,
3579 &result);
3580 if (!W_ERROR_IS_OK(result)) {
3581 goto done;
3584 done:
3585 if (is_valid_policy_hnd(&gdi_handle)) {
3586 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3588 if (is_valid_policy_hnd(&handle)) {
3589 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3592 return result;
3595 /* List of commands exported by this module */
3596 struct cmd_set spoolss_commands[] = {
3598 { "SPOOLSS" },
3600 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3601 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3602 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3603 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3604 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3605 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3606 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3607 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3608 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3609 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3610 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3611 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3612 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3613 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3614 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3615 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3616 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3617 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3618 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3619 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3620 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3621 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3622 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3623 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3624 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3625 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3626 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3627 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3628 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3629 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3630 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3631 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3632 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3633 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3634 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3635 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3637 { NULL }