s3-rpcclient: fix two more invalid typecasts in spoolss commands.
[Samba/gebeck_regimport.git] / source3 / rpcclient / cmd_spoolss.c
blob6b62bdeb526fc78d90752448b3451245d38ee78f
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"
29 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
30 { \
31 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
32 _cli->srv_name_slash, _arg); \
33 W_ERROR_HAVE_NO_MEMORY(_printername); \
36 /* The version int is used by getdrivers. Note that
37 all architecture strings that support mutliple
38 versions must be grouped together since enumdrivers
39 uses this property to prevent issuing multiple
40 enumdriver calls for the same arch */
43 static const struct print_architecture_table_node archi_table[]= {
45 {"Windows 4.0", "WIN40", 0 },
46 {"Windows NT x86", "W32X86", 2 },
47 {"Windows NT x86", "W32X86", 3 },
48 {"Windows NT R4000", "W32MIPS", 2 },
49 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
50 {"Windows NT PowerPC", "W32PPC", 2 },
51 {"Windows IA64", "IA64", 3 },
52 {"Windows x64", "x64", 3 },
53 {NULL, "", -1 }
56 /**
57 * @file
59 * rpcclient module for SPOOLSS rpc pipe.
61 * This generally just parses and checks command lines, and then calls
62 * a cli_spoolss function.
63 **/
65 /****************************************************************************
66 function to do the mapping between the long architecture name and
67 the short one.
68 ****************************************************************************/
70 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
72 int i=-1;
74 DEBUG(107,("Getting architecture dependant directory\n"));
75 do {
76 i++;
77 } while ( (archi_table[i].long_archi!=NULL ) &&
78 StrCaseCmp(long_archi, archi_table[i].long_archi) );
80 if (archi_table[i].long_archi==NULL) {
81 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
82 return NULL;
85 /* this might be client code - but shouldn't this be an fstrcpy etc? */
88 DEBUGADD(108,("index: [%d]\n", i));
89 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
90 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
92 return archi_table[i].short_archi;
95 /****************************************************************************
96 ****************************************************************************/
98 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
99 TALLOC_CTX *mem_ctx,
100 int argc, const char **argv)
102 WERROR werror;
103 struct policy_handle hnd;
105 if (argc != 2) {
106 printf("Usage: %s <printername>\n", argv[0]);
107 return WERR_OK;
110 if (!cli)
111 return WERR_GENERAL_FAILURE;
113 /* Open the printer handle */
115 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
116 argv[1],
117 PRINTER_ALL_ACCESS,
118 &hnd);
119 if (W_ERROR_IS_OK(werror)) {
120 printf("Printer %s opened successfully\n", argv[1]);
121 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
123 if (!W_ERROR_IS_OK(werror)) {
124 printf("Error closing printer handle! (%s)\n",
125 get_dos_error_msg(werror));
129 return werror;
133 /****************************************************************************
134 ****************************************************************************/
136 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
138 if (!r)
139 return;
141 printf("\tprintername:[%s]\n", r->printername);
142 printf("\tservername:[%s]\n", r->servername);
143 printf("\tcjobs:[0x%x]\n", r->cjobs);
144 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
145 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
146 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
147 r->time.day, r->time.day_of_week);
148 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
149 r->time.second, r->time.millisecond);
151 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
152 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
154 printf("\tversion:[0x%x]\n", r->version);
155 printf("\tfree_build:[0x%x]\n", r->free_build);
156 printf("\tspooling:[0x%x]\n", r->spooling);
157 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
158 printf("\tsession_counter:[0x%x]\n", r->session_counter);
159 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
160 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
161 printf("\tjob_error:[0x%x]\n", r->job_error);
162 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
163 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
164 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
165 printf("\tchange_id:[0x%x]\n", r->change_id);
166 printf("\tlast_error: %s\n", win_errstr(r->last_error));
167 printf("\tstatus:[0x%x]\n", r->status);
168 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
169 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
170 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
171 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
172 printf("\tref_ic:[0x%x]\n", r->ref_ic);
173 printf("\treserved2:[0x%x]\n", r->reserved2);
174 printf("\treserved3:[0x%x]\n", r->reserved3);
176 printf("\n");
179 /****************************************************************************
180 ****************************************************************************/
182 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
184 printf("\tflags:[0x%x]\n", r->flags);
185 printf("\tname:[%s]\n", r->name);
186 printf("\tdescription:[%s]\n", r->description);
187 printf("\tcomment:[%s]\n", r->comment);
189 printf("\n");
192 /****************************************************************************
193 ****************************************************************************/
195 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
197 printf("\tservername:[%s]\n", r->servername);
198 printf("\tprintername:[%s]\n", r->printername);
199 printf("\tsharename:[%s]\n", r->sharename);
200 printf("\tportname:[%s]\n", r->portname);
201 printf("\tdrivername:[%s]\n", r->drivername);
202 printf("\tcomment:[%s]\n", r->comment);
203 printf("\tlocation:[%s]\n", r->location);
204 printf("\tsepfile:[%s]\n", r->sepfile);
205 printf("\tprintprocessor:[%s]\n", r->printprocessor);
206 printf("\tdatatype:[%s]\n", r->datatype);
207 printf("\tparameters:[%s]\n", r->parameters);
208 printf("\tattributes:[0x%x]\n", r->attributes);
209 printf("\tpriority:[0x%x]\n", r->priority);
210 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
211 printf("\tstarttime:[0x%x]\n", r->starttime);
212 printf("\tuntiltime:[0x%x]\n", r->untiltime);
213 printf("\tstatus:[0x%x]\n", r->status);
214 printf("\tcjobs:[0x%x]\n", r->cjobs);
215 printf("\taverageppm:[0x%x]\n", r->averageppm);
217 if (r->secdesc)
218 display_sec_desc(r->secdesc);
220 printf("\n");
223 /****************************************************************************
224 ****************************************************************************/
226 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
228 display_sec_desc(r->secdesc);
230 printf("\n");
233 /****************************************************************************
234 ****************************************************************************/
236 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
238 printf("\tservername:[%s]\n", r->servername);
239 printf("\tprintername:[%s]\n", r->printername);
240 printf("\tattributes:[0x%x]\n", r->attributes);
241 printf("\n");
244 /****************************************************************************
245 ****************************************************************************/
247 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
249 printf("\tprintername:[%s]\n", r->printername);
250 printf("\tportname:[%s]\n", r->portname);
251 printf("\tattributes:[0x%x]\n", r->attributes);
252 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
253 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
254 printf("\n");
257 /****************************************************************************
258 ****************************************************************************/
260 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
262 printf("\tstatus:[0x%x]\n", r->status);
263 printf("\n");
266 /****************************************************************************
267 ****************************************************************************/
269 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
271 printf("\tguid:[%s]\n", r->guid);
272 printf("\taction:[0x%x]\n", r->action);
273 printf("\n");
276 /****************************************************************************
277 ****************************************************************************/
279 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
280 TALLOC_CTX *mem_ctx,
281 int argc, const char **argv)
283 WERROR result;
284 uint32_t level = 1;
285 union spoolss_PrinterInfo *info;
286 uint32_t i, count;
287 const char *name;
288 uint32_t flags = PRINTER_ENUM_LOCAL;
290 if (argc > 4) {
291 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
292 return WERR_OK;
295 if (argc >= 2) {
296 level = atoi(argv[1]);
299 if (argc >= 3) {
300 name = argv[2];
301 } else {
302 name = cli->srv_name_slash;
305 if (argc == 4) {
306 flags = atoi(argv[3]);
309 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
310 flags,
311 name,
312 level,
314 &count,
315 &info);
316 if (W_ERROR_IS_OK(result)) {
318 if (!count) {
319 printf ("No printers returned.\n");
320 goto done;
323 for (i = 0; i < count; i++) {
324 switch (level) {
325 case 0:
326 display_print_info0(&info[i].info0);
327 break;
328 case 1:
329 display_print_info1(&info[i].info1);
330 break;
331 case 2:
332 display_print_info2(&info[i].info2);
333 break;
334 case 3:
335 display_print_info3(&info[i].info3);
336 break;
337 case 4:
338 display_print_info4(&info[i].info4);
339 break;
340 case 5:
341 display_print_info5(&info[i].info5);
342 break;
343 case 6:
344 display_print_info6(&info[i].info6);
345 break;
346 default:
347 printf("unknown info level %d\n", level);
348 goto done;
352 done:
354 return result;
357 /****************************************************************************
358 ****************************************************************************/
360 static void display_port_info_1(struct spoolss_PortInfo1 *r)
362 printf("\tPort Name:\t[%s]\n", r->port_name);
365 /****************************************************************************
366 ****************************************************************************/
368 static void display_port_info_2(struct spoolss_PortInfo2 *r)
370 printf("\tPort Name:\t[%s]\n", r->port_name);
371 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
372 printf("\tDescription:\t[%s]\n", r->description);
373 printf("\tPort Type:\t" );
374 if (r->port_type) {
375 int comma = 0; /* hack */
376 printf( "[" );
377 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
378 printf( "Read" );
379 comma = 1;
381 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
382 printf( "%sWrite", comma ? ", " : "" );
383 comma = 1;
385 /* These two have slightly different interpretations
386 on 95/98/ME but I'm disregarding that for now */
387 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
388 printf( "%sRedirected", comma ? ", " : "" );
389 comma = 1;
391 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
392 printf( "%sNet-Attached", comma ? ", " : "" );
394 printf( "]\n" );
395 } else {
396 printf( "[Unset]\n" );
398 printf("\tReserved:\t[%d]\n", r->reserved);
399 printf("\n");
402 /****************************************************************************
403 ****************************************************************************/
405 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
406 TALLOC_CTX *mem_ctx, int argc,
407 const char **argv)
409 WERROR result;
410 uint32_t level = 1;
411 uint32_t count;
412 union spoolss_PortInfo *info;
414 if (argc > 2) {
415 printf("Usage: %s [level]\n", argv[0]);
416 return WERR_OK;
419 if (argc == 2) {
420 level = atoi(argv[1]);
423 /* Enumerate ports */
425 result = rpccli_spoolss_enumports(cli, mem_ctx,
426 cli->srv_name_slash,
427 level,
429 &count,
430 &info);
431 if (W_ERROR_IS_OK(result)) {
432 int i;
434 for (i = 0; i < count; i++) {
435 switch (level) {
436 case 1:
437 display_port_info_1(&info[i].info1);
438 break;
439 case 2:
440 display_port_info_2(&info[i].info2);
441 break;
442 default:
443 printf("unknown info level %d\n", level);
444 break;
449 return result;
452 /****************************************************************************
453 ****************************************************************************/
455 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
456 TALLOC_CTX *mem_ctx,
457 int argc, const char **argv)
459 struct policy_handle pol;
460 WERROR result;
461 NTSTATUS status;
462 uint32_t info_level = 2;
463 union spoolss_PrinterInfo info;
464 struct spoolss_SetPrinterInfoCtr info_ctr;
465 struct spoolss_SetPrinterInfo2 info2;
466 const char *printername, *comment = NULL;
467 struct spoolss_DevmodeContainer devmode_ctr;
468 struct sec_desc_buf secdesc_ctr;
470 if (argc == 1 || argc > 3) {
471 printf("Usage: %s printername comment\n", argv[0]);
473 return WERR_OK;
476 /* Open a printer handle */
477 if (argc == 3) {
478 comment = argv[2];
481 ZERO_STRUCT(devmode_ctr);
482 ZERO_STRUCT(secdesc_ctr);
484 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
486 /* get a printer handle */
487 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
488 printername,
489 PRINTER_ALL_ACCESS,
490 &pol);
491 if (!W_ERROR_IS_OK(result))
492 goto done;
494 /* Get printer info */
495 result = rpccli_spoolss_getprinter(cli, mem_ctx,
496 &pol,
497 info_level,
499 &info);
500 if (!W_ERROR_IS_OK(result))
501 goto done;
504 /* Modify the comment. */
505 info2.servername = info.info2.servername;
506 info2.printername = info.info2.printername;
507 info2.sharename = info.info2.sharename;
508 info2.portname = info.info2.portname;
509 info2.drivername = info.info2.drivername;
510 info2.comment = comment;
511 info2.location = info.info2.location;
512 info2.devmode_ptr = 0;
513 info2.sepfile = info.info2.sepfile;
514 info2.printprocessor = info.info2.printprocessor;
515 info2.datatype = info.info2.datatype;
516 info2.parameters = info.info2.parameters;
517 info2.secdesc_ptr = 0;
518 info2.attributes = info.info2.attributes;
519 info2.priority = info.info2.priority;
520 info2.defaultpriority = info.info2.defaultpriority;
521 info2.starttime = info.info2.starttime;
522 info2.untiltime = info.info2.untiltime;
523 info2.status = info.info2.status;
524 info2.cjobs = info.info2.cjobs;
525 info2.averageppm = info.info2.averageppm;
527 info_ctr.level = 2;
528 info_ctr.info.info2 = &info2;
530 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
531 &pol,
532 &info_ctr,
533 &devmode_ctr,
534 &secdesc_ctr,
535 0, /* command */
536 &result);
537 if (W_ERROR_IS_OK(result))
538 printf("Success in setting comment.\n");
540 done:
541 if (is_valid_policy_hnd(&pol))
542 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
544 return result;
547 /****************************************************************************
548 ****************************************************************************/
550 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
551 TALLOC_CTX *mem_ctx,
552 int argc, const char **argv)
554 struct policy_handle pol;
555 WERROR result;
556 NTSTATUS status;
557 uint32_t info_level = 2;
558 union spoolss_PrinterInfo info;
559 const char *printername,
560 *new_printername = NULL;
561 struct spoolss_SetPrinterInfoCtr info_ctr;
562 struct spoolss_SetPrinterInfo2 info2;
563 struct spoolss_DevmodeContainer devmode_ctr;
564 struct sec_desc_buf secdesc_ctr;
566 ZERO_STRUCT(devmode_ctr);
567 ZERO_STRUCT(secdesc_ctr);
569 if (argc == 1 || argc > 3) {
570 printf("Usage: %s printername new_printername\n", argv[0]);
572 return WERR_OK;
575 /* Open a printer handle */
576 if (argc == 3) {
577 new_printername = argv[2];
580 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
582 /* get a printer handle */
583 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
584 printername,
585 PRINTER_ALL_ACCESS,
586 &pol);
587 if (!W_ERROR_IS_OK(result))
588 goto done;
590 /* Get printer info */
591 result = rpccli_spoolss_getprinter(cli, mem_ctx,
592 &pol,
593 info_level,
595 &info);
596 if (!W_ERROR_IS_OK(result))
597 goto done;
599 /* Modify the printername. */
600 info2.servername = info.info2.servername;
601 info2.printername = new_printername;
602 info2.sharename = info.info2.sharename;
603 info2.portname = info.info2.portname;
604 info2.drivername = info.info2.drivername;
605 info2.comment = info.info2.comment;
606 info2.location = info.info2.location;
607 info2.devmode_ptr = 0;
608 info2.sepfile = info.info2.sepfile;
609 info2.printprocessor = info.info2.printprocessor;
610 info2.datatype = info.info2.datatype;
611 info2.parameters = info.info2.parameters;
612 info2.secdesc_ptr = 0;
613 info2.attributes = info.info2.attributes;
614 info2.priority = info.info2.priority;
615 info2.defaultpriority = info.info2.defaultpriority;
616 info2.starttime = info.info2.starttime;
617 info2.untiltime = info.info2.untiltime;
618 info2.status = info.info2.status;
619 info2.cjobs = info.info2.cjobs;
620 info2.averageppm = info.info2.averageppm;
622 info_ctr.level = 2;
623 info_ctr.info.info2 = &info2;
625 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
626 &pol,
627 &info_ctr,
628 &devmode_ctr,
629 &secdesc_ctr,
630 0, /* command */
631 &result);
632 if (W_ERROR_IS_OK(result))
633 printf("Success in setting printername.\n");
635 done:
636 if (is_valid_policy_hnd(&pol))
637 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
639 return result;
642 /****************************************************************************
643 ****************************************************************************/
645 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
646 TALLOC_CTX *mem_ctx,
647 int argc, const char **argv)
649 struct policy_handle pol;
650 WERROR result;
651 uint32_t level = 1;
652 const char *printername;
653 union spoolss_PrinterInfo info;
655 if (argc == 1 || argc > 3) {
656 printf("Usage: %s <printername> [level]\n", argv[0]);
657 return WERR_OK;
660 /* Open a printer handle */
661 if (argc == 3) {
662 level = atoi(argv[2]);
665 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
667 /* get a printer handle */
669 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
670 printername,
671 SEC_FLAG_MAXIMUM_ALLOWED,
672 &pol);
673 if (!W_ERROR_IS_OK(result)) {
674 goto done;
677 /* Get printer info */
679 result = rpccli_spoolss_getprinter(cli, mem_ctx,
680 &pol,
681 level,
683 &info);
684 if (!W_ERROR_IS_OK(result)) {
685 goto done;
688 /* Display printer info */
689 switch (level) {
690 case 0:
691 display_print_info0(&info.info0);
692 break;
693 case 1:
694 display_print_info1(&info.info1);
695 break;
696 case 2:
697 display_print_info2(&info.info2);
698 break;
699 case 3:
700 display_print_info3(&info.info3);
701 break;
702 case 4:
703 display_print_info4(&info.info4);
704 break;
705 case 5:
706 display_print_info5(&info.info5);
707 break;
708 case 6:
709 display_print_info6(&info.info6);
710 break;
711 case 7:
712 display_print_info7(&info.info7);
713 break;
714 default:
715 printf("unknown info level %d\n", level);
716 break;
718 done:
719 if (is_valid_policy_hnd(&pol)) {
720 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
723 return result;
726 /****************************************************************************
727 ****************************************************************************/
729 static void display_reg_value(struct regval_blob value)
731 const char *text = NULL;
732 DATA_BLOB blob;
734 switch(value.type) {
735 case REG_DWORD:
736 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
737 *((uint32_t *) value.data_p));
738 break;
739 case REG_SZ:
740 blob = data_blob_const(value.data_p, value.size);
741 pull_reg_sz(talloc_tos(), NULL, &blob, &text);
742 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
743 break;
744 case REG_BINARY: {
745 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
746 size_t i, len;
747 printf("%s: REG_BINARY:", value.valuename);
748 len = strlen(hex);
749 for (i=0; i<len; i++) {
750 if (hex[i] == '\0') {
751 break;
753 if (i%40 == 0) {
754 putchar('\n');
756 putchar(hex[i]);
758 TALLOC_FREE(hex);
759 putchar('\n');
760 break;
762 case REG_MULTI_SZ: {
763 uint32_t i;
764 const char **values;
765 blob = data_blob_const(value.data_p, value.size);
767 if (!pull_reg_multi_sz(NULL, NULL, &blob, &values)) {
768 d_printf("pull_reg_multi_sz failed\n");
769 break;
772 printf("%s: REG_MULTI_SZ: \n", value.valuename);
773 for (i=0; values[i] != NULL; i++) {
774 d_printf("%s\n", values[i]);
776 TALLOC_FREE(values);
777 break;
779 default:
780 printf("%s: unknown type %d\n", value.valuename, value.type);
785 /****************************************************************************
786 ****************************************************************************/
788 static void display_printer_data(const char *v,
789 enum winreg_Type type,
790 uint8_t *data,
791 uint32_t length)
793 int i;
794 union spoolss_PrinterData r;
795 DATA_BLOB blob = data_blob_const(data, length);
796 WERROR result;
798 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
799 if (!W_ERROR_IS_OK(result)) {
800 return;
803 switch (type) {
804 case REG_DWORD:
805 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
806 break;
807 case REG_SZ:
808 printf("%s: REG_SZ: %s\n", v, r.string);
809 break;
810 case REG_BINARY: {
811 char *hex = hex_encode_talloc(NULL,
812 r.binary.data, r.binary.length);
813 size_t len;
814 printf("%s: REG_BINARY:", v);
815 len = strlen(hex);
816 for (i=0; i<len; i++) {
817 if (hex[i] == '\0') {
818 break;
820 if (i%40 == 0) {
821 putchar('\n');
823 putchar(hex[i]);
825 TALLOC_FREE(hex);
826 putchar('\n');
827 break;
829 case REG_MULTI_SZ:
830 printf("%s: REG_MULTI_SZ: ", v);
831 for (i=0; r.string_array[i] != NULL; i++) {
832 printf("%s ", r.string_array[i]);
834 printf("\n");
835 break;
836 default:
837 printf("%s: unknown type 0x%02x:\n", v, type);
838 break;
842 /****************************************************************************
843 ****************************************************************************/
845 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
846 TALLOC_CTX *mem_ctx,
847 int argc, const char **argv)
849 struct policy_handle pol;
850 WERROR result;
851 fstring printername;
852 const char *valuename;
853 enum winreg_Type type;
854 uint8_t *data;
855 uint32_t needed;
857 if (argc != 3) {
858 printf("Usage: %s <printername> <valuename>\n", argv[0]);
859 printf("<printername> of . queries print server\n");
860 return WERR_OK;
862 valuename = argv[2];
864 /* Open a printer handle */
866 if (strncmp(argv[1], ".", sizeof(".")) == 0)
867 fstrcpy(printername, cli->srv_name_slash);
868 else
869 slprintf(printername, sizeof(printername)-1, "%s\\%s",
870 cli->srv_name_slash, argv[1]);
872 /* get a printer handle */
874 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
875 printername,
876 SEC_FLAG_MAXIMUM_ALLOWED,
877 &pol);
878 if (!W_ERROR_IS_OK(result))
879 goto done;
881 /* Get printer info */
883 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
884 &pol,
885 valuename,
887 &type,
888 &needed,
889 &data);
890 if (!W_ERROR_IS_OK(result))
891 goto done;
893 /* Display printer data */
895 display_printer_data(valuename, type, data, needed);
897 done:
898 if (is_valid_policy_hnd(&pol))
899 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
901 return result;
904 /****************************************************************************
905 ****************************************************************************/
907 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
908 TALLOC_CTX *mem_ctx,
909 int argc, const char **argv)
911 struct policy_handle pol;
912 WERROR result;
913 NTSTATUS status;
914 fstring printername;
915 const char *valuename, *keyname;
917 enum winreg_Type type;
918 uint8_t *data = NULL;
919 uint32_t offered = 0;
920 uint32_t needed;
922 if (argc != 4) {
923 printf("Usage: %s <printername> <keyname> <valuename>\n",
924 argv[0]);
925 printf("<printername> of . queries print server\n");
926 return WERR_OK;
928 valuename = argv[3];
929 keyname = argv[2];
931 /* Open a printer handle */
933 if (strncmp(argv[1], ".", sizeof(".")) == 0)
934 fstrcpy(printername, cli->srv_name_slash);
935 else
936 slprintf(printername, sizeof(printername)-1, "%s\\%s",
937 cli->srv_name_slash, argv[1]);
939 /* get a printer handle */
941 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
942 printername,
943 SEC_FLAG_MAXIMUM_ALLOWED,
944 &pol);
945 if (!W_ERROR_IS_OK(result))
946 goto done;
948 /* Get printer info */
950 data = talloc_zero_array(mem_ctx, uint8_t, offered);
951 if (!data) {
952 goto done;
955 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
956 &pol,
957 keyname,
958 valuename,
959 &type,
960 data,
961 offered,
962 &needed,
963 &result);
964 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
965 offered = needed;
966 data = talloc_zero_array(mem_ctx, uint8_t, offered);
967 if (!data) {
968 goto done;
970 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
971 &pol,
972 keyname,
973 valuename,
974 &type,
975 data,
976 offered,
977 &needed,
978 &result);
981 if (!NT_STATUS_IS_OK(status)) {
982 goto done;
985 if (!W_ERROR_IS_OK(result))
986 goto done;
988 /* Display printer data */
990 display_printer_data(valuename, type, data, needed);
993 done:
994 if (is_valid_policy_hnd(&pol))
995 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
997 return result;
1000 /****************************************************************************
1001 ****************************************************************************/
1003 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1005 if (!r) {
1006 return;
1009 printf("Printer Driver Info 1:\n");
1010 printf("\tDriver Name: [%s]\n", r->driver_name);
1011 printf("\n");
1014 /****************************************************************************
1015 ****************************************************************************/
1017 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1019 if (!r) {
1020 return;
1023 printf("Printer Driver Info 2:\n");
1024 printf("\tVersion: [%x]\n", r->version);
1025 printf("\tDriver Name: [%s]\n", r->driver_name);
1026 printf("\tArchitecture: [%s]\n", r->architecture);
1027 printf("\tDriver Path: [%s]\n", r->driver_path);
1028 printf("\tDatafile: [%s]\n", r->data_file);
1029 printf("\tConfigfile: [%s]\n", r->config_file);
1030 printf("\n");
1033 /****************************************************************************
1034 ****************************************************************************/
1036 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1038 int i;
1040 if (!r) {
1041 return;
1044 printf("Printer Driver Info 3:\n");
1045 printf("\tVersion: [%x]\n", r->version);
1046 printf("\tDriver Name: [%s]\n", r->driver_name);
1047 printf("\tArchitecture: [%s]\n", r->architecture);
1048 printf("\tDriver Path: [%s]\n", r->driver_path);
1049 printf("\tDatafile: [%s]\n", r->data_file);
1050 printf("\tConfigfile: [%s]\n", r->config_file);
1051 printf("\tHelpfile: [%s]\n", r->help_file);
1053 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1054 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1057 printf("\tMonitorname: [%s]\n", r->monitor_name);
1058 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1059 printf("\n");
1062 /****************************************************************************
1063 ****************************************************************************/
1065 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1067 int i;
1069 if (!r) {
1070 return;
1073 printf("Printer Driver Info 4:\n");
1074 printf("\tVersion: [%x]\n", r->version);
1075 printf("\tDriver Name: [%s]\n", r->driver_name);
1076 printf("\tArchitecture: [%s]\n", r->architecture);
1077 printf("\tDriver Path: [%s]\n", r->driver_path);
1078 printf("\tDatafile: [%s]\n", r->data_file);
1079 printf("\tConfigfile: [%s]\n", r->config_file);
1080 printf("\tHelpfile: [%s]\n", r->help_file);
1082 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1083 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1086 printf("\tMonitorname: [%s]\n", r->monitor_name);
1087 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1089 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1090 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1092 printf("\n");
1095 /****************************************************************************
1096 ****************************************************************************/
1098 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1100 if (!r) {
1101 return;
1104 printf("Printer Driver Info 5:\n");
1105 printf("\tVersion: [%x]\n", r->version);
1106 printf("\tDriver Name: [%s]\n", r->driver_name);
1107 printf("\tArchitecture: [%s]\n", r->architecture);
1108 printf("\tDriver Path: [%s]\n", r->driver_path);
1109 printf("\tDatafile: [%s]\n", r->data_file);
1110 printf("\tConfigfile: [%s]\n", r->config_file);
1111 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1112 printf("\tConfig Version: [0x%x]\n", r->config_version);
1113 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1114 printf("\n");
1117 /****************************************************************************
1118 ****************************************************************************/
1120 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1122 int i;
1124 if (!r) {
1125 return;
1128 printf("Printer Driver Info 6:\n");
1129 printf("\tVersion: [%x]\n", r->version);
1130 printf("\tDriver Name: [%s]\n", r->driver_name);
1131 printf("\tArchitecture: [%s]\n", r->architecture);
1132 printf("\tDriver Path: [%s]\n", r->driver_path);
1133 printf("\tDatafile: [%s]\n", r->data_file);
1134 printf("\tConfigfile: [%s]\n", r->config_file);
1135 printf("\tHelpfile: [%s]\n", r->help_file);
1137 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1138 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1141 printf("\tMonitorname: [%s]\n", r->monitor_name);
1142 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1144 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1145 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1148 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1149 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1150 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1151 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1152 printf("\tHardware ID: [%s]\n", r->hardware_id);
1153 printf("\tProvider: [%s]\n", r->provider);
1155 printf("\n");
1158 /****************************************************************************
1159 ****************************************************************************/
1161 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1163 int i;
1165 if (!r) {
1166 return;
1169 printf("Printer Driver Info 8:\n");
1170 printf("\tVersion: [%x]\n", r->version);
1171 printf("\tDriver Name: [%s]\n", r->driver_name);
1172 printf("\tArchitecture: [%s]\n", r->architecture);
1173 printf("\tDriver Path: [%s]\n", r->driver_path);
1174 printf("\tDatafile: [%s]\n", r->data_file);
1175 printf("\tConfigfile: [%s]\n", r->config_file);
1176 printf("\tHelpfile: [%s]\n", r->help_file);
1177 printf("\tMonitorname: [%s]\n", r->monitor_name);
1178 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1180 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1181 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1184 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1185 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1188 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1189 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1190 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1191 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1192 printf("\tHardware ID: [%s]\n", r->hardware_id);
1193 printf("\tProvider: [%s]\n", r->provider);
1194 printf("\tPrint Processor: [%s]\n", r->print_processor);
1195 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1196 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1197 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1199 printf("\tInf Path: [%s]\n", r->inf_path);
1200 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1201 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1202 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1204 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1205 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1206 (long long unsigned int)r->min_inbox_driver_ver_version);
1208 printf("\n");
1211 /****************************************************************************
1212 ****************************************************************************/
1214 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1215 TALLOC_CTX *mem_ctx,
1216 int argc, const char **argv)
1218 struct policy_handle pol;
1219 WERROR werror;
1220 uint32_t level = 3;
1221 const char *printername;
1222 uint32_t i;
1223 bool success = false;
1224 union spoolss_DriverInfo info;
1225 uint32_t server_major_version;
1226 uint32_t server_minor_version;
1228 if ((argc == 1) || (argc > 3)) {
1229 printf("Usage: %s <printername> [level]\n", argv[0]);
1230 return WERR_OK;
1233 /* get the arguments need to open the printer handle */
1235 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1237 if (argc == 3) {
1238 level = atoi(argv[2]);
1241 /* Open a printer handle */
1243 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1244 printername,
1245 PRINTER_ACCESS_USE,
1246 &pol);
1247 if (!W_ERROR_IS_OK(werror)) {
1248 printf("Error opening printer handle for %s!\n", printername);
1249 return werror;
1252 /* loop through and print driver info level for each architecture */
1254 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1256 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1257 &pol,
1258 archi_table[i].long_archi,
1259 level,
1260 0, /* offered */
1261 archi_table[i].version,
1263 &info,
1264 &server_major_version,
1265 &server_minor_version);
1266 if (!W_ERROR_IS_OK(werror)) {
1267 continue;
1270 /* need at least one success */
1272 success = true;
1274 printf("\n[%s]\n", archi_table[i].long_archi);
1276 switch (level) {
1277 case 1:
1278 display_print_driver1(&info.info1);
1279 break;
1280 case 2:
1281 display_print_driver2(&info.info2);
1282 break;
1283 case 3:
1284 display_print_driver3(&info.info3);
1285 break;
1286 case 4:
1287 display_print_driver4(&info.info4);
1288 break;
1289 case 5:
1290 display_print_driver5(&info.info5);
1291 break;
1292 case 6:
1293 display_print_driver6(&info.info6);
1294 break;
1295 case 8:
1296 display_print_driver8(&info.info8);
1297 break;
1298 default:
1299 printf("unknown info level %d\n", level);
1300 break;
1304 /* Cleanup */
1306 if (is_valid_policy_hnd(&pol)) {
1307 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1310 if (success) {
1311 werror = WERR_OK;
1314 return werror;
1317 /****************************************************************************
1318 ****************************************************************************/
1320 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1321 TALLOC_CTX *mem_ctx,
1322 const char *architecture,
1323 uint32_t level)
1325 WERROR werror;
1326 uint32_t count = 0;
1327 union spoolss_DriverInfo *info = NULL;
1328 uint32_t j;
1330 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1331 cli->srv_name_slash,
1332 architecture,
1333 level,
1335 &count,
1336 &info);
1338 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1339 printf("Server does not support environment [%s]\n",
1340 architecture);
1341 return WERR_OK;
1344 if (count == 0) {
1345 return WERR_OK;
1348 if (!W_ERROR_IS_OK(werror)) {
1349 printf("Error getting driver for environment [%s] - %s\n",
1350 architecture, win_errstr(werror));
1351 return werror;
1354 printf("\n[%s]\n", architecture);
1356 switch (level) {
1357 case 1:
1358 for (j=0; j < count; j++) {
1359 display_print_driver1(&info[j].info1);
1361 break;
1362 case 2:
1363 for (j=0; j < count; j++) {
1364 display_print_driver2(&info[j].info2);
1366 break;
1367 case 3:
1368 for (j=0; j < count; j++) {
1369 display_print_driver3(&info[j].info3);
1371 break;
1372 case 4:
1373 for (j=0; j < count; j++) {
1374 display_print_driver4(&info[j].info4);
1376 break;
1377 case 5:
1378 for (j=0; j < count; j++) {
1379 display_print_driver5(&info[j].info5);
1381 break;
1382 case 6:
1383 for (j=0; j < count; j++) {
1384 display_print_driver6(&info[j].info6);
1386 break;
1387 case 8:
1388 for (j=0; j < count; j++) {
1389 display_print_driver8(&info[j].info8);
1391 break;
1392 default:
1393 printf("unknown info level %d\n", level);
1394 return WERR_UNKNOWN_LEVEL;
1397 return werror;
1400 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1401 TALLOC_CTX *mem_ctx,
1402 int argc, const char **argv)
1404 WERROR werror = WERR_OK;
1405 uint32_t level = 1;
1406 uint32_t i;
1407 const char *architecture = NULL;
1409 if (argc > 3) {
1410 printf("Usage: enumdrivers [level] [architecture]\n");
1411 return WERR_OK;
1414 if (argc >= 2) {
1415 level = atoi(argv[1]);
1418 if (argc == 3) {
1419 architecture = argv[2];
1422 if (architecture) {
1423 return enum_driver_by_architecture(cli, mem_ctx,
1424 architecture,
1425 level);
1428 /* loop through and print driver info level for each architecture */
1429 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1430 /* check to see if we already asked for this architecture string */
1432 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1433 continue;
1436 werror = enum_driver_by_architecture(cli, mem_ctx,
1437 archi_table[i].long_archi,
1438 level);
1439 if (!W_ERROR_IS_OK(werror)) {
1440 break;
1444 return werror;
1447 /****************************************************************************
1448 ****************************************************************************/
1450 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1452 printf("\tDirectory Name:[%s]\n", r->directory_name);
1455 /****************************************************************************
1456 ****************************************************************************/
1458 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1459 TALLOC_CTX *mem_ctx,
1460 int argc, const char **argv)
1462 WERROR result;
1463 NTSTATUS status;
1464 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1465 DATA_BLOB buffer;
1466 uint32_t offered;
1467 union spoolss_DriverDirectoryInfo info;
1468 uint32_t needed;
1470 if (argc > 2) {
1471 printf("Usage: %s [environment]\n", argv[0]);
1472 return WERR_OK;
1475 /* Get the arguments need to open the printer handle */
1477 if (argc == 2) {
1478 env = argv[1];
1481 /* Get the directory. Only use Info level 1 */
1483 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1484 cli->srv_name_slash,
1485 env,
1487 NULL, /* buffer */
1488 0, /* offered */
1489 NULL, /* info */
1490 &needed,
1491 &result);
1492 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1493 offered = needed;
1494 buffer = data_blob_talloc_zero(mem_ctx, needed);
1496 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1497 cli->srv_name_slash,
1498 env,
1500 &buffer,
1501 offered,
1502 &info,
1503 &needed,
1504 &result);
1507 if (W_ERROR_IS_OK(result)) {
1508 display_printdriverdir_1(&info.info1);
1511 return result;
1514 /****************************************************************************
1515 ****************************************************************************/
1517 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1518 struct spoolss_AddDriverInfo3 *info,
1519 const char *arch)
1522 int i;
1524 for (i=0; archi_table[i].long_archi != NULL; i++)
1526 if (strcmp(arch, archi_table[i].short_archi) == 0)
1528 info->version = archi_table[i].version;
1529 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1530 break;
1534 if (archi_table[i].long_archi == NULL)
1536 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1539 return;
1543 /**************************************************************************
1544 wrapper for strtok to get the next parameter from a delimited list.
1545 Needed to handle the empty parameter string denoted by "NULL"
1546 *************************************************************************/
1548 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1549 const char *delim, const char **dest,
1550 char **saveptr)
1552 char *ptr;
1554 /* get the next token */
1555 ptr = strtok_r(str, delim, saveptr);
1557 /* a string of 'NULL' is used to represent an empty
1558 parameter because two consecutive delimiters
1559 will not return an empty string. See man strtok(3)
1560 for details */
1561 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1562 ptr = NULL;
1565 if (dest != NULL) {
1566 *dest = talloc_strdup(mem_ctx, ptr);
1569 return ptr;
1572 /********************************************************************************
1573 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1574 string in the form of
1575 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1576 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1577 <Default Data Type>:<Comma Separated list of Files>
1578 *******************************************************************************/
1580 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1581 char *args)
1583 char *str, *str2;
1584 int count = 0;
1585 char *saveptr = NULL;
1586 struct spoolss_StringArray *deps;
1587 const char **file_array = NULL;
1588 int i;
1590 /* fill in the UNISTR fields */
1591 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1592 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1593 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1594 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1595 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1596 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1597 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1599 /* <Comma Separated List of Dependent Files> */
1600 /* save the beginning of the string */
1601 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1602 str = str2;
1604 /* begin to strip out each filename */
1605 str = strtok_r(str, ",", &saveptr);
1607 /* no dependent files, we are done */
1608 if (!str) {
1609 return true;
1612 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1613 if (!deps) {
1614 return false;
1617 while (str != NULL) {
1618 add_string_to_array(deps, str, &file_array, &count);
1619 str = strtok_r(NULL, ",", &saveptr);
1622 deps->string = talloc_zero_array(deps, const char *, count + 1);
1623 if (!deps->string) {
1624 return false;
1627 for (i=0; i < count; i++) {
1628 deps->string[i] = file_array[i];
1631 r->dependent_files = deps;
1633 return true;
1636 /****************************************************************************
1637 ****************************************************************************/
1639 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1640 TALLOC_CTX *mem_ctx,
1641 int argc, const char **argv)
1643 WERROR result;
1644 NTSTATUS status;
1645 uint32_t level = 3;
1646 struct spoolss_AddDriverInfoCtr info_ctr;
1647 struct spoolss_AddDriverInfo3 info3;
1648 const char *arch;
1649 char *driver_args;
1651 /* parse the command arguments */
1652 if (argc != 3 && argc != 4)
1654 printf ("Usage: %s <Environment> \\\n", argv[0]);
1655 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1656 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1657 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1658 printf ("\t[version]\n");
1660 return WERR_OK;
1663 /* Fill in the spoolss_AddDriverInfo3 struct */
1664 ZERO_STRUCT(info3);
1666 arch = cmd_spoolss_get_short_archi(argv[1]);
1667 if (!arch) {
1668 printf ("Error Unknown architechture [%s]\n", argv[1]);
1669 return WERR_INVALID_PARAM;
1672 set_drv_info_3_env(mem_ctx, &info3, arch);
1674 driver_args = talloc_strdup( mem_ctx, argv[2] );
1675 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1677 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1678 return WERR_INVALID_PARAM;
1681 /* if printer driver version specified, override the default version
1682 * used by the architecture. This allows installation of Windows
1683 * 2000 (version 3) printer drivers. */
1684 if (argc == 4)
1686 info3.version = atoi(argv[3]);
1690 info_ctr.level = level;
1691 info_ctr.info.info3 = &info3;
1693 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1694 cli->srv_name_slash,
1695 &info_ctr,
1696 &result);
1697 if (!NT_STATUS_IS_OK(status)) {
1698 return ntstatus_to_werror(status);
1700 if (W_ERROR_IS_OK(result)) {
1701 printf ("Printer Driver %s successfully installed.\n",
1702 info3.driver_name);
1705 return result;
1709 /****************************************************************************
1710 ****************************************************************************/
1712 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1713 TALLOC_CTX *mem_ctx,
1714 int argc, const char **argv)
1716 WERROR result;
1717 struct spoolss_SetPrinterInfoCtr info_ctr;
1718 struct spoolss_SetPrinterInfo2 info2;
1720 /* parse the command arguments */
1721 if (argc != 5)
1723 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1724 return WERR_OK;
1727 /* Fill in the DRIVER_INFO_2 struct */
1728 ZERO_STRUCT(info2);
1730 info2.printername = argv[1];
1731 info2.drivername = argv[3];
1732 info2.sharename = argv[2];
1733 info2.portname = argv[4];
1734 info2.comment = "Created by rpcclient";
1735 info2.printprocessor = "winprint";
1736 info2.datatype = "RAW";
1737 info2.devmode_ptr = 0;
1738 info2.secdesc_ptr = 0;
1739 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1740 info2.priority = 0;
1741 info2.defaultpriority = 0;
1742 info2.starttime = 0;
1743 info2.untiltime = 0;
1745 /* These three fields must not be used by AddPrinter()
1746 as defined in the MS Platform SDK documentation..
1747 --jerry
1748 info2.status = 0;
1749 info2.cjobs = 0;
1750 info2.averageppm = 0;
1753 info_ctr.level = 2;
1754 info_ctr.info.info2 = &info2;
1756 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1757 &info_ctr);
1758 if (W_ERROR_IS_OK(result))
1759 printf ("Printer %s successfully installed.\n", argv[1]);
1761 return result;
1764 /****************************************************************************
1765 ****************************************************************************/
1767 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1768 TALLOC_CTX *mem_ctx,
1769 int argc, const char **argv)
1771 struct policy_handle pol;
1772 WERROR result;
1773 NTSTATUS status;
1774 uint32_t level = 2;
1775 const char *printername;
1776 union spoolss_PrinterInfo info;
1777 struct spoolss_SetPrinterInfoCtr info_ctr;
1778 struct spoolss_SetPrinterInfo2 info2;
1779 struct spoolss_DevmodeContainer devmode_ctr;
1780 struct sec_desc_buf secdesc_ctr;
1782 ZERO_STRUCT(devmode_ctr);
1783 ZERO_STRUCT(secdesc_ctr);
1785 /* parse the command arguments */
1786 if (argc != 3)
1788 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1789 return WERR_OK;
1792 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1794 /* Get a printer handle */
1796 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1797 printername,
1798 PRINTER_ALL_ACCESS,
1799 &pol);
1800 if (!W_ERROR_IS_OK(result))
1801 goto done;
1803 /* Get printer info */
1805 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1806 &pol,
1807 level,
1809 &info);
1810 if (!W_ERROR_IS_OK(result)) {
1811 printf ("Unable to retrieve printer information!\n");
1812 goto done;
1815 /* Set the printer driver */
1817 info2.servername = info.info2.servername;
1818 info2.printername = info.info2.printername;
1819 info2.sharename = info.info2.sharename;
1820 info2.portname = info.info2.portname;
1821 info2.drivername = argv[2];
1822 info2.comment = info.info2.comment;
1823 info2.location = info.info2.location;
1824 info2.devmode_ptr = 0;
1825 info2.sepfile = info.info2.sepfile;
1826 info2.printprocessor = info.info2.printprocessor;
1827 info2.datatype = info.info2.datatype;
1828 info2.parameters = info.info2.parameters;
1829 info2.secdesc_ptr = 0;
1830 info2.attributes = info.info2.attributes;
1831 info2.priority = info.info2.priority;
1832 info2.defaultpriority = info.info2.defaultpriority;
1833 info2.starttime = info.info2.starttime;
1834 info2.untiltime = info.info2.untiltime;
1835 info2.status = info.info2.status;
1836 info2.cjobs = info.info2.cjobs;
1837 info2.averageppm = info.info2.averageppm;
1839 info_ctr.level = 2;
1840 info_ctr.info.info2 = &info2;
1842 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1843 &pol,
1844 &info_ctr,
1845 &devmode_ctr,
1846 &secdesc_ctr,
1847 0, /* command */
1848 &result);
1849 if (!W_ERROR_IS_OK(result)) {
1850 printf("SetPrinter call failed!\n");
1851 goto done;;
1854 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1856 done:
1857 /* Cleanup */
1859 if (is_valid_policy_hnd(&pol))
1860 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1862 return result;
1866 /****************************************************************************
1867 ****************************************************************************/
1869 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1870 TALLOC_CTX *mem_ctx,
1871 int argc, const char **argv)
1873 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1874 NTSTATUS status;
1876 int i;
1877 int vers = -1;
1879 const char *arch = NULL;
1880 uint32_t delete_flags = 0;
1882 /* parse the command arguments */
1883 if (argc < 2 || argc > 4) {
1884 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1885 return WERR_OK;
1888 if (argc >= 3)
1889 arch = argv[2];
1890 if (argc == 4)
1891 vers = atoi (argv[3]);
1893 if (vers >= 0) {
1894 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1897 /* delete the driver for all architectures */
1898 for (i=0; archi_table[i].long_archi; i++) {
1900 if (arch && !strequal( archi_table[i].long_archi, arch))
1901 continue;
1903 if (vers >= 0 && archi_table[i].version != vers)
1904 continue;
1906 /* make the call to remove the driver */
1907 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1908 cli->srv_name_slash,
1909 archi_table[i].long_archi,
1910 argv[1],
1911 delete_flags,
1912 archi_table[i].version,
1913 &result);
1915 if ( !W_ERROR_IS_OK(result) )
1917 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1918 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1919 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1922 else
1924 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1925 archi_table[i].long_archi, archi_table[i].version);
1926 ret = WERR_OK;
1930 return ret;
1934 /****************************************************************************
1935 ****************************************************************************/
1937 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1938 TALLOC_CTX *mem_ctx,
1939 int argc, const char **argv)
1941 WERROR result = WERR_OK;
1942 NTSTATUS status;
1943 int i;
1945 /* parse the command arguments */
1946 if (argc != 2) {
1947 printf ("Usage: %s <driver>\n", argv[0]);
1948 return WERR_OK;
1951 /* delete the driver for all architectures */
1952 for (i=0; archi_table[i].long_archi; i++) {
1953 /* make the call to remove the driver */
1954 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1955 cli->srv_name_slash,
1956 archi_table[i].long_archi,
1957 argv[1],
1958 &result);
1959 if (!NT_STATUS_IS_OK(status)) {
1960 return result;
1962 if ( !W_ERROR_IS_OK(result) ) {
1963 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1964 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1965 argv[1], archi_table[i].long_archi,
1966 W_ERROR_V(result));
1968 } else {
1969 printf ("Driver %s removed for arch [%s].\n", argv[1],
1970 archi_table[i].long_archi);
1974 return result;
1977 /****************************************************************************
1978 ****************************************************************************/
1980 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1981 TALLOC_CTX *mem_ctx,
1982 int argc, const char **argv)
1984 WERROR result;
1985 NTSTATUS status;
1986 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1987 DATA_BLOB buffer;
1988 uint32_t offered;
1989 union spoolss_PrintProcessorDirectoryInfo info;
1990 uint32_t needed;
1992 /* parse the command arguments */
1993 if (argc > 2) {
1994 printf ("Usage: %s [environment]\n", argv[0]);
1995 return WERR_OK;
1998 if (argc == 2) {
1999 environment = argv[1];
2002 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2003 cli->srv_name_slash,
2004 environment,
2006 NULL, /* buffer */
2007 0, /* offered */
2008 NULL, /* info */
2009 &needed,
2010 &result);
2011 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2012 offered = needed;
2013 buffer = data_blob_talloc_zero(mem_ctx, needed);
2015 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2016 cli->srv_name_slash,
2017 environment,
2019 &buffer,
2020 offered,
2021 &info,
2022 &needed,
2023 &result);
2026 if (W_ERROR_IS_OK(result)) {
2027 printf("%s\n", info.info1.directory_name);
2030 return result;
2033 /****************************************************************************
2034 ****************************************************************************/
2036 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2037 int argc, const char **argv)
2039 struct policy_handle handle;
2040 WERROR werror;
2041 NTSTATUS status;
2042 const char *printername;
2043 union spoolss_AddFormInfo info;
2044 struct spoolss_AddFormInfo1 info1;
2045 struct spoolss_AddFormInfo2 info2;
2046 uint32_t level = 1;
2048 /* Parse the command arguments */
2050 if (argc < 3 || argc > 5) {
2051 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2052 return WERR_OK;
2055 /* Get a printer handle */
2057 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2059 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2060 printername,
2061 PRINTER_ALL_ACCESS,
2062 &handle);
2063 if (!W_ERROR_IS_OK(werror))
2064 goto done;
2066 /* Dummy up some values for the form data */
2068 if (argc == 4) {
2069 level = atoi(argv[3]);
2072 switch (level) {
2073 case 1:
2074 info1.flags = SPOOLSS_FORM_USER;
2075 info1.form_name = argv[2];
2076 info1.size.width = 100;
2077 info1.size.height = 100;
2078 info1.area.left = 0;
2079 info1.area.top = 10;
2080 info1.area.right = 20;
2081 info1.area.bottom = 30;
2083 info.info1 = &info1;
2085 break;
2086 case 2:
2087 info2.flags = SPOOLSS_FORM_USER;
2088 info2.form_name = argv[2];
2089 info2.size.width = 100;
2090 info2.size.height = 100;
2091 info2.area.left = 0;
2092 info2.area.top = 10;
2093 info2.area.right = 20;
2094 info2.area.bottom = 30;
2095 info2.keyword = argv[2];
2096 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2097 info2.mui_dll = NULL;
2098 info2.ressource_id = 0;
2099 info2.display_name = argv[2];
2100 info2.lang_id = 0;
2102 info.info2 = &info2;
2104 break;
2107 /* Add the form */
2110 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2111 &handle,
2112 level,
2113 info,
2114 &werror);
2116 done:
2117 if (is_valid_policy_hnd(&handle))
2118 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2120 return werror;
2123 /****************************************************************************
2124 ****************************************************************************/
2126 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2127 int argc, const char **argv)
2129 struct policy_handle handle;
2130 WERROR werror;
2131 NTSTATUS status;
2132 const char *printername;
2133 union spoolss_AddFormInfo info;
2134 struct spoolss_AddFormInfo1 info1;
2136 /* Parse the command arguments */
2138 if (argc != 3) {
2139 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2140 return WERR_OK;
2143 /* Get a printer handle */
2145 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2147 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2148 printername,
2149 SEC_FLAG_MAXIMUM_ALLOWED,
2150 &handle);
2151 if (!W_ERROR_IS_OK(werror))
2152 goto done;
2154 /* Dummy up some values for the form data */
2156 info1.flags = SPOOLSS_FORM_PRINTER;
2157 info1.size.width = 100;
2158 info1.size.height = 100;
2159 info1.area.left = 0;
2160 info1.area.top = 1000;
2161 info1.area.right = 2000;
2162 info1.area.bottom = 3000;
2163 info1.form_name = argv[2];
2165 info.info1 = &info1;
2167 /* Set the form */
2169 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2170 &handle,
2171 argv[2],
2173 info,
2174 &werror);
2176 done:
2177 if (is_valid_policy_hnd(&handle))
2178 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2180 return werror;
2183 /****************************************************************************
2184 ****************************************************************************/
2186 static const char *get_form_flag(int form_flag)
2188 switch (form_flag) {
2189 case SPOOLSS_FORM_USER:
2190 return "FORM_USER";
2191 case SPOOLSS_FORM_BUILTIN:
2192 return "FORM_BUILTIN";
2193 case SPOOLSS_FORM_PRINTER:
2194 return "FORM_PRINTER";
2195 default:
2196 return "unknown";
2200 /****************************************************************************
2201 ****************************************************************************/
2203 static void display_form_info1(struct spoolss_FormInfo1 *r)
2205 printf("%s\n" \
2206 "\tflag: %s (%d)\n" \
2207 "\twidth: %d, length: %d\n" \
2208 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2209 r->form_name, get_form_flag(r->flags), r->flags,
2210 r->size.width, r->size.height,
2211 r->area.left, r->area.right,
2212 r->area.top, r->area.bottom);
2215 /****************************************************************************
2216 ****************************************************************************/
2218 static void display_form_info2(struct spoolss_FormInfo2 *r)
2220 printf("%s\n" \
2221 "\tflag: %s (%d)\n" \
2222 "\twidth: %d, length: %d\n" \
2223 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2224 r->form_name, get_form_flag(r->flags), r->flags,
2225 r->size.width, r->size.height,
2226 r->area.left, r->area.right,
2227 r->area.top, r->area.bottom);
2228 printf("\tkeyword: %s\n", r->keyword);
2229 printf("\tstring_type: 0x%08x\n", r->string_type);
2230 printf("\tmui_dll: %s\n", r->mui_dll);
2231 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2232 printf("\tdisplay_name: %s\n", r->display_name);
2233 printf("\tlang_id: %d\n", r->lang_id);
2234 printf("\n");
2237 /****************************************************************************
2238 ****************************************************************************/
2240 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2241 int argc, const char **argv)
2243 struct policy_handle handle;
2244 WERROR werror;
2245 NTSTATUS status;
2246 const char *printername;
2247 DATA_BLOB buffer;
2248 uint32_t offered = 0;
2249 union spoolss_FormInfo info;
2250 uint32_t needed;
2251 uint32_t level = 1;
2253 /* Parse the command arguments */
2255 if (argc < 3 || argc > 5) {
2256 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2257 return WERR_OK;
2260 /* Get a printer handle */
2262 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2264 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2265 printername,
2266 SEC_FLAG_MAXIMUM_ALLOWED,
2267 &handle);
2268 if (!W_ERROR_IS_OK(werror))
2269 goto done;
2271 if (argc == 4) {
2272 level = atoi(argv[3]);
2275 /* Get the form */
2277 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2278 &handle,
2279 argv[2],
2280 level,
2281 NULL,
2282 offered,
2283 &info,
2284 &needed,
2285 &werror);
2286 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2287 buffer = data_blob_talloc_zero(mem_ctx, needed);
2288 offered = needed;
2289 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2290 &handle,
2291 argv[2],
2292 level,
2293 &buffer,
2294 offered,
2295 &info,
2296 &needed,
2297 &werror);
2300 if (!NT_STATUS_IS_OK(status)) {
2301 return werror;
2304 switch (level) {
2305 case 1:
2306 display_form_info1(&info.info1);
2307 break;
2308 case 2:
2309 display_form_info2(&info.info2);
2310 break;
2313 done:
2314 if (is_valid_policy_hnd(&handle))
2315 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2317 return werror;
2320 /****************************************************************************
2321 ****************************************************************************/
2323 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2324 TALLOC_CTX *mem_ctx, int argc,
2325 const char **argv)
2327 struct policy_handle handle;
2328 WERROR werror;
2329 NTSTATUS status;
2330 const char *printername;
2332 /* Parse the command arguments */
2334 if (argc != 3) {
2335 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2336 return WERR_OK;
2339 /* Get a printer handle */
2341 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2343 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2344 printername,
2345 SEC_FLAG_MAXIMUM_ALLOWED,
2346 &handle);
2347 if (!W_ERROR_IS_OK(werror))
2348 goto done;
2350 /* Delete the form */
2352 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2353 &handle,
2354 argv[2],
2355 &werror);
2356 if (!NT_STATUS_IS_OK(status)) {
2357 return ntstatus_to_werror(status);
2360 done:
2361 if (is_valid_policy_hnd(&handle))
2362 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2364 return werror;
2367 /****************************************************************************
2368 ****************************************************************************/
2370 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2371 TALLOC_CTX *mem_ctx, int argc,
2372 const char **argv)
2374 struct policy_handle handle;
2375 WERROR werror;
2376 const char *printername;
2377 uint32_t num_forms, level = 1, i;
2378 union spoolss_FormInfo *forms;
2380 /* Parse the command arguments */
2382 if (argc < 2 || argc > 4) {
2383 printf ("Usage: %s <printer> [level]\n", argv[0]);
2384 return WERR_OK;
2387 /* Get a printer handle */
2389 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2391 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2392 printername,
2393 SEC_FLAG_MAXIMUM_ALLOWED,
2394 &handle);
2395 if (!W_ERROR_IS_OK(werror))
2396 goto done;
2398 if (argc == 3) {
2399 level = atoi(argv[2]);
2402 /* Enumerate forms */
2404 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2405 &handle,
2406 level,
2408 &num_forms,
2409 &forms);
2411 if (!W_ERROR_IS_OK(werror))
2412 goto done;
2414 /* Display output */
2416 for (i = 0; i < num_forms; i++) {
2417 switch (level) {
2418 case 1:
2419 display_form_info1(&forms[i].info1);
2420 break;
2421 case 2:
2422 display_form_info2(&forms[i].info2);
2423 break;
2427 done:
2428 if (is_valid_policy_hnd(&handle))
2429 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2431 return werror;
2434 /****************************************************************************
2435 ****************************************************************************/
2437 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2438 TALLOC_CTX *mem_ctx,
2439 int argc, const char **argv)
2441 WERROR result;
2442 NTSTATUS status;
2443 const char *printername;
2444 struct policy_handle pol;
2445 union spoolss_PrinterInfo info;
2446 enum winreg_Type type;
2447 union spoolss_PrinterData data;
2448 DATA_BLOB blob;
2450 /* parse the command arguments */
2451 if (argc < 5) {
2452 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2453 " <value> <data>\n",
2454 argv[0]);
2455 return WERR_OK;
2458 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2460 type = REG_NONE;
2462 if (strequal(argv[2], "string")) {
2463 type = REG_SZ;
2466 if (strequal(argv[2], "binary")) {
2467 type = REG_BINARY;
2470 if (strequal(argv[2], "dword")) {
2471 type = REG_DWORD;
2474 if (strequal(argv[2], "multistring")) {
2475 type = REG_MULTI_SZ;
2478 if (type == REG_NONE) {
2479 printf("Unknown data type: %s\n", argv[2]);
2480 result = WERR_INVALID_PARAM;
2481 goto done;
2484 /* get a printer handle */
2486 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2487 printername,
2488 SEC_FLAG_MAXIMUM_ALLOWED,
2489 &pol);
2490 if (!W_ERROR_IS_OK(result)) {
2491 goto done;
2494 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2495 &pol,
2498 &info);
2499 if (!W_ERROR_IS_OK(result)) {
2500 goto done;
2503 printf("%s\n", current_timestring(mem_ctx, true));
2504 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2506 /* Set the printer data */
2508 switch (type) {
2509 case REG_SZ:
2510 data.string = talloc_strdup(mem_ctx, argv[4]);
2511 W_ERROR_HAVE_NO_MEMORY(data.string);
2512 break;
2513 case REG_DWORD:
2514 data.value = strtoul(argv[4], NULL, 10);
2515 break;
2516 case REG_BINARY:
2517 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2518 break;
2519 case REG_MULTI_SZ: {
2520 int i, num_strings;
2521 const char **strings = NULL;
2523 for (i=4; i<argc; i++) {
2524 if (strcmp(argv[i], "NULL") == 0) {
2525 argv[i] = "";
2527 if (!add_string_to_array(mem_ctx, argv[i],
2528 &strings,
2529 &num_strings)) {
2530 result = WERR_NOMEM;
2531 goto done;
2534 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2535 if (!data.string_array) {
2536 result = WERR_NOMEM;
2537 goto done;
2539 for (i=0; i < num_strings; i++) {
2540 data.string_array[i] = strings[i];
2542 break;
2544 default:
2545 printf("Unknown data type: %s\n", argv[2]);
2546 result = WERR_INVALID_PARAM;
2547 goto done;
2550 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2551 if (!W_ERROR_IS_OK(result)) {
2552 goto done;
2555 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2556 &pol,
2557 argv[3], /* value_name */
2558 type,
2559 blob.data,
2560 blob.length,
2561 &result);
2562 if (!W_ERROR_IS_OK(result)) {
2563 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2564 goto done;
2566 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2568 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2569 &pol,
2572 &info);
2573 if (!W_ERROR_IS_OK(result)) {
2574 goto done;
2577 printf("%s\n", current_timestring(mem_ctx, true));
2578 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2580 done:
2581 /* cleanup */
2582 if (is_valid_policy_hnd(&pol)) {
2583 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2586 return result;
2589 /****************************************************************************
2590 ****************************************************************************/
2592 static void display_job_info1(struct spoolss_JobInfo1 *r)
2594 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2595 r->user_name, r->document_name, r->text_status, r->pages_printed,
2596 r->total_pages);
2599 /****************************************************************************
2600 ****************************************************************************/
2602 static void display_job_info2(struct spoolss_JobInfo2 *r)
2604 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2605 r->position, r->job_id,
2606 r->user_name, r->document_name, r->text_status, r->pages_printed,
2607 r->total_pages, r->size);
2610 /****************************************************************************
2611 ****************************************************************************/
2613 static void display_job_info3(struct spoolss_JobInfo3 *r)
2615 printf("jobid[%d], next_jobid[%d]\n",
2616 r->job_id, r->next_job_id);
2619 /****************************************************************************
2620 ****************************************************************************/
2622 static void display_job_info4(struct spoolss_JobInfo4 *r)
2624 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2625 r->position, r->job_id,
2626 r->user_name, r->document_name, r->text_status, r->pages_printed,
2627 r->total_pages, r->size, r->size_high);
2630 /****************************************************************************
2631 ****************************************************************************/
2633 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2634 TALLOC_CTX *mem_ctx, int argc,
2635 const char **argv)
2637 WERROR result;
2638 uint32_t level = 1, count, i;
2639 const char *printername;
2640 struct policy_handle hnd;
2641 union spoolss_JobInfo *info;
2643 if (argc < 2 || argc > 3) {
2644 printf("Usage: %s printername [level]\n", argv[0]);
2645 return WERR_OK;
2648 if (argc == 3) {
2649 level = atoi(argv[2]);
2652 /* Open printer handle */
2654 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2656 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2657 printername,
2658 SEC_FLAG_MAXIMUM_ALLOWED,
2659 &hnd);
2660 if (!W_ERROR_IS_OK(result))
2661 goto done;
2663 /* Enumerate ports */
2665 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2666 &hnd,
2667 0, /* firstjob */
2668 1000, /* numjobs */
2669 level,
2671 &count,
2672 &info);
2673 if (!W_ERROR_IS_OK(result)) {
2674 goto done;
2677 for (i = 0; i < count; i++) {
2678 switch (level) {
2679 case 1:
2680 display_job_info1(&info[i].info1);
2681 break;
2682 case 2:
2683 display_job_info2(&info[i].info2);
2684 break;
2685 default:
2686 d_printf("unknown info level %d\n", level);
2687 break;
2691 done:
2692 if (is_valid_policy_hnd(&hnd)) {
2693 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2696 return result;
2699 /****************************************************************************
2700 ****************************************************************************/
2702 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2703 TALLOC_CTX *mem_ctx, int argc,
2704 const char **argv)
2706 WERROR result;
2707 const char *printername;
2708 struct policy_handle hnd;
2709 uint32_t job_id;
2710 uint32_t level = 1;
2711 union spoolss_JobInfo info;
2713 if (argc < 3 || argc > 4) {
2714 printf("Usage: %s printername job_id [level]\n", argv[0]);
2715 return WERR_OK;
2718 job_id = atoi(argv[2]);
2720 if (argc == 4) {
2721 level = atoi(argv[3]);
2724 /* Open printer handle */
2726 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2728 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2729 printername,
2730 SEC_FLAG_MAXIMUM_ALLOWED,
2731 &hnd);
2732 if (!W_ERROR_IS_OK(result)) {
2733 goto done;
2736 /* Enumerate ports */
2738 result = rpccli_spoolss_getjob(cli, mem_ctx,
2739 &hnd,
2740 job_id,
2741 level,
2743 &info);
2745 if (!W_ERROR_IS_OK(result)) {
2746 goto done;
2749 switch (level) {
2750 case 1:
2751 display_job_info1(&info.info1);
2752 break;
2753 case 2:
2754 display_job_info2(&info.info2);
2755 break;
2756 case 3:
2757 display_job_info3(&info.info3);
2758 break;
2759 case 4:
2760 display_job_info4(&info.info4);
2761 break;
2762 default:
2763 d_printf("unknown info level %d\n", level);
2764 break;
2767 done:
2768 if (is_valid_policy_hnd(&hnd)) {
2769 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2772 return result;
2775 /****************************************************************************
2776 ****************************************************************************/
2778 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2779 TALLOC_CTX *mem_ctx, int argc,
2780 const char **argv)
2782 WERROR result;
2783 NTSTATUS status;
2784 const char *printername;
2785 struct policy_handle hnd;
2786 uint32_t job_id;
2787 enum spoolss_JobControl command;
2789 if (argc != 4) {
2790 printf("Usage: %s printername job_id command\n", argv[0]);
2791 return WERR_OK;
2794 job_id = atoi(argv[2]);
2795 command = atoi(argv[3]);
2797 /* Open printer handle */
2799 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2801 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2802 printername,
2803 SEC_FLAG_MAXIMUM_ALLOWED,
2804 &hnd);
2805 if (!W_ERROR_IS_OK(result)) {
2806 goto done;
2809 /* Set Job */
2811 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2812 &hnd,
2813 job_id,
2814 NULL,
2815 command,
2816 &result);
2818 if (!W_ERROR_IS_OK(result)) {
2819 goto done;
2822 done:
2823 if (is_valid_policy_hnd(&hnd)) {
2824 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2827 return result;
2830 /****************************************************************************
2831 ****************************************************************************/
2833 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2834 TALLOC_CTX *mem_ctx, int argc,
2835 const char **argv)
2837 WERROR result;
2838 NTSTATUS status;
2839 uint32_t i = 0;
2840 const char *printername;
2841 struct policy_handle hnd;
2842 uint32_t value_offered = 0;
2843 const char *value_name = NULL;
2844 uint32_t value_needed;
2845 enum winreg_Type type;
2846 uint8_t *data = NULL;
2847 uint32_t data_offered = 0;
2848 uint32_t data_needed;
2850 if (argc != 2) {
2851 printf("Usage: %s printername\n", argv[0]);
2852 return WERR_OK;
2855 /* Open printer handle */
2857 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2859 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2860 printername,
2861 SEC_FLAG_MAXIMUM_ALLOWED,
2862 &hnd);
2863 if (!W_ERROR_IS_OK(result)) {
2864 goto done;
2867 /* Enumerate data */
2869 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2870 &hnd,
2872 value_name,
2873 value_offered,
2874 &value_needed,
2875 &type,
2876 data,
2877 data_offered,
2878 &data_needed,
2879 &result);
2881 data_offered = data_needed;
2882 value_offered = value_needed;
2883 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2884 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2886 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2888 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2889 &hnd,
2890 i++,
2891 value_name,
2892 value_offered,
2893 &value_needed,
2894 &type,
2895 data,
2896 data_offered,
2897 &data_needed,
2898 &result);
2899 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2900 struct regval_blob v;
2901 fstrcpy(v.valuename, value_name);
2902 v.type = type;
2903 v.size = data_offered;
2904 v.data_p = data;
2905 display_reg_value(v);
2909 if (W_ERROR_V(result) == ERRnomoreitems) {
2910 result = W_ERROR(ERRsuccess);
2913 done:
2914 if (is_valid_policy_hnd(&hnd)) {
2915 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2918 return result;
2921 /****************************************************************************
2922 ****************************************************************************/
2924 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2925 TALLOC_CTX *mem_ctx, int argc,
2926 const char **argv)
2928 WERROR result;
2929 uint32_t i;
2930 const char *printername;
2931 struct policy_handle hnd;
2932 uint32_t count;
2933 struct spoolss_PrinterEnumValues *info;
2935 if (argc != 3) {
2936 printf("Usage: %s printername <keyname>\n", argv[0]);
2937 return WERR_OK;
2940 /* Open printer handle */
2942 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2944 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2945 printername,
2946 SEC_FLAG_MAXIMUM_ALLOWED,
2947 &hnd);
2948 if (!W_ERROR_IS_OK(result)) {
2949 goto done;
2952 /* Enumerate subkeys */
2954 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2955 &hnd,
2956 argv[2],
2958 &count,
2959 &info);
2960 if (!W_ERROR_IS_OK(result)) {
2961 goto done;
2964 for (i=0; i < count; i++) {
2965 display_printer_data(info[i].value_name,
2966 info[i].type,
2967 info[i].data->data,
2968 info[i].data->length);
2971 done:
2972 if (is_valid_policy_hnd(&hnd)) {
2973 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2976 return result;
2979 /****************************************************************************
2980 ****************************************************************************/
2982 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2983 TALLOC_CTX *mem_ctx, int argc,
2984 const char **argv)
2986 WERROR result;
2987 const char *printername;
2988 const char *keyname = NULL;
2989 struct policy_handle hnd;
2990 const char **key_buffer = NULL;
2991 int i;
2992 uint32_t offered = 0;
2994 if (argc < 2 || argc > 4) {
2995 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
2996 return WERR_OK;
2999 if (argc >= 3) {
3000 keyname = argv[2];
3001 } else {
3002 keyname = "";
3005 if (argc == 4) {
3006 offered = atoi(argv[3]);
3009 /* Open printer handle */
3011 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3013 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3014 printername,
3015 SEC_FLAG_MAXIMUM_ALLOWED,
3016 &hnd);
3017 if (!W_ERROR_IS_OK(result)) {
3018 goto done;
3021 /* Enumerate subkeys */
3023 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3024 &hnd,
3025 keyname,
3026 &key_buffer,
3027 offered);
3029 if (!W_ERROR_IS_OK(result)) {
3030 goto done;
3033 for (i=0; key_buffer && key_buffer[i]; i++) {
3034 printf("%s\n", key_buffer[i]);
3037 done:
3039 if (is_valid_policy_hnd(&hnd)) {
3040 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3043 return result;
3046 /****************************************************************************
3047 ****************************************************************************/
3049 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3050 TALLOC_CTX *mem_ctx, int argc,
3051 const char **argv)
3053 const char *printername;
3054 const char *clientname;
3055 struct policy_handle hnd;
3056 WERROR result;
3057 NTSTATUS status;
3058 struct spoolss_NotifyOption option;
3060 if (argc != 2) {
3061 printf("Usage: %s printername\n", argv[0]);
3062 result = WERR_OK;
3063 goto done;
3066 /* Open printer */
3068 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3070 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3071 printername,
3072 SEC_FLAG_MAXIMUM_ALLOWED,
3073 &hnd);
3074 if (!W_ERROR_IS_OK(result)) {
3075 printf("Error opening %s\n", argv[1]);
3076 goto done;
3079 /* Create spool options */
3081 option.version = 2;
3082 option.count = 2;
3084 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3085 if (option.types == NULL) {
3086 result = WERR_NOMEM;
3087 goto done;
3090 option.types[0].type = PRINTER_NOTIFY_TYPE;
3091 option.types[0].count = 1;
3092 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3093 if (option.types[0].fields == NULL) {
3094 result = WERR_NOMEM;
3095 goto done;
3097 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3099 option.types[1].type = JOB_NOTIFY_TYPE;
3100 option.types[1].count = 1;
3101 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3102 if (option.types[1].fields == NULL) {
3103 result = WERR_NOMEM;
3104 goto done;
3106 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3108 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3109 if (!clientname) {
3110 result = WERR_NOMEM;
3111 goto done;
3114 /* Send rffpcnex */
3116 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3117 &hnd,
3120 clientname,
3121 123,
3122 &option,
3123 &result);
3124 if (!W_ERROR_IS_OK(result)) {
3125 printf("Error rffpcnex %s\n", argv[1]);
3126 goto done;
3129 done:
3130 if (is_valid_policy_hnd(&hnd))
3131 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3133 return result;
3136 /****************************************************************************
3137 ****************************************************************************/
3139 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3140 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3142 union spoolss_PrinterInfo info1, info2;
3143 WERROR werror;
3144 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3146 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3147 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3148 hnd1,
3151 &info1);
3152 if ( !W_ERROR_IS_OK(werror) ) {
3153 printf("failed (%s)\n", win_errstr(werror));
3154 talloc_destroy(mem_ctx);
3155 return false;
3157 printf("ok\n");
3159 printf("Retrieving printer properties for %s...", cli2->desthost);
3160 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3161 hnd2,
3164 &info2);
3165 if ( !W_ERROR_IS_OK(werror) ) {
3166 printf("failed (%s)\n", win_errstr(werror));
3167 talloc_destroy(mem_ctx);
3168 return false;
3170 printf("ok\n");
3172 talloc_destroy(mem_ctx);
3174 return true;
3177 /****************************************************************************
3178 ****************************************************************************/
3180 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3181 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3183 union spoolss_PrinterInfo info1, info2;
3184 WERROR werror;
3185 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3186 SEC_DESC *sd1, *sd2;
3187 bool result = true;
3190 printf("Retrieving printer security for %s...", cli1->desthost);
3191 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3192 hnd1,
3195 &info1);
3196 if ( !W_ERROR_IS_OK(werror) ) {
3197 printf("failed (%s)\n", win_errstr(werror));
3198 result = false;
3199 goto done;
3201 printf("ok\n");
3203 printf("Retrieving printer security for %s...", cli2->desthost);
3204 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3205 hnd2,
3208 &info2);
3209 if ( !W_ERROR_IS_OK(werror) ) {
3210 printf("failed (%s)\n", win_errstr(werror));
3211 result = false;
3212 goto done;
3214 printf("ok\n");
3217 printf("++ ");
3219 sd1 = info1.info3.secdesc;
3220 sd2 = info2.info3.secdesc;
3222 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3223 printf("NULL secdesc!\n");
3224 result = false;
3225 goto done;
3228 if (!security_descriptor_equal( sd1, sd2 ) ) {
3229 printf("Security Descriptors *not* equal!\n");
3230 result = false;
3231 goto done;
3234 printf("Security descriptors match\n");
3236 done:
3237 talloc_destroy(mem_ctx);
3238 return result;
3242 /****************************************************************************
3243 ****************************************************************************/
3245 extern struct user_auth_info *rpcclient_auth_info;
3247 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3248 TALLOC_CTX *mem_ctx, int argc,
3249 const char **argv)
3251 const char *printername;
3252 char *printername_path = NULL;
3253 struct cli_state *cli_server2 = NULL;
3254 struct rpc_pipe_client *cli2 = NULL;
3255 struct policy_handle hPrinter1, hPrinter2;
3256 NTSTATUS nt_status;
3257 WERROR werror;
3259 if ( argc != 3 ) {
3260 printf("Usage: %s <printer> <server>\n", argv[0]);
3261 return WERR_OK;
3264 printername = argv[1];
3266 /* first get the connection to the remote server */
3268 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3269 NULL, 0,
3270 "IPC$", "IPC",
3271 get_cmdline_auth_info_username(rpcclient_auth_info),
3272 lp_workgroup(),
3273 get_cmdline_auth_info_password(rpcclient_auth_info),
3274 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3275 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3277 if ( !NT_STATUS_IS_OK(nt_status) )
3278 return WERR_GENERAL_FAILURE;
3280 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3281 &cli2);
3282 if (!NT_STATUS_IS_OK(nt_status)) {
3283 printf("failed to open spoolss pipe on server %s (%s)\n",
3284 argv[2], nt_errstr(nt_status));
3285 return WERR_GENERAL_FAILURE;
3288 /* now open up both printers */
3290 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3292 printf("Opening %s...", printername_path);
3294 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3295 printername_path,
3296 PRINTER_ALL_ACCESS,
3297 &hPrinter1);
3298 if ( !W_ERROR_IS_OK(werror) ) {
3299 printf("failed (%s)\n", win_errstr(werror));
3300 goto done;
3302 printf("ok\n");
3304 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3306 printf("Opening %s...", printername_path);
3307 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3308 printername_path,
3309 PRINTER_ALL_ACCESS,
3310 &hPrinter2);
3311 if ( !W_ERROR_IS_OK(werror) ) {
3312 printf("failed (%s)\n", win_errstr(werror));
3313 goto done;
3315 printf("ok\n");
3317 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3318 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3319 #if 0
3320 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3321 #endif
3324 done:
3325 /* cleanup */
3327 printf("Closing printers...");
3328 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3329 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3330 printf("ok\n");
3332 /* close the second remote connection */
3334 cli_shutdown( cli_server2 );
3335 return WERR_OK;
3338 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3340 printf("print_processor_name: %s\n", r->print_processor_name);
3343 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3344 TALLOC_CTX *mem_ctx, int argc,
3345 const char **argv)
3347 WERROR werror;
3348 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3349 uint32_t num_procs, level = 1, i;
3350 union spoolss_PrintProcessorInfo *procs;
3352 /* Parse the command arguments */
3354 if (argc < 1 || argc > 4) {
3355 printf ("Usage: %s [environment] [level]\n", argv[0]);
3356 return WERR_OK;
3359 if (argc >= 2) {
3360 environment = argv[1];
3363 if (argc == 3) {
3364 level = atoi(argv[2]);
3367 /* Enumerate Print Processors */
3369 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3370 cli->srv_name_slash,
3371 environment,
3372 level,
3374 &num_procs,
3375 &procs);
3376 if (!W_ERROR_IS_OK(werror))
3377 goto done;
3379 /* Display output */
3381 for (i = 0; i < num_procs; i++) {
3382 switch (level) {
3383 case 1:
3384 display_proc_info1(&procs[i].info1);
3385 break;
3389 done:
3390 return werror;
3393 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3395 printf("name_array: %s\n", r->name_array);
3398 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3399 TALLOC_CTX *mem_ctx, int argc,
3400 const char **argv)
3402 WERROR werror;
3403 const char *print_processor_name = "winprint";
3404 uint32_t num_procs, level = 1, i;
3405 union spoolss_PrintProcDataTypesInfo *procs;
3407 /* Parse the command arguments */
3409 if (argc < 1 || argc > 4) {
3410 printf ("Usage: %s [environment] [level]\n", argv[0]);
3411 return WERR_OK;
3414 if (argc >= 2) {
3415 print_processor_name = argv[1];
3418 if (argc == 3) {
3419 level = atoi(argv[2]);
3422 /* Enumerate Print Processor Data Types */
3424 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3425 cli->srv_name_slash,
3426 print_processor_name,
3427 level,
3429 &num_procs,
3430 &procs);
3431 if (!W_ERROR_IS_OK(werror))
3432 goto done;
3434 /* Display output */
3436 for (i = 0; i < num_procs; i++) {
3437 switch (level) {
3438 case 1:
3439 display_proc_data_types_info1(&procs[i].info1);
3440 break;
3444 done:
3445 return werror;
3448 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3450 printf("monitor_name: %s\n", r->monitor_name);
3453 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3455 printf("monitor_name: %s\n", r->monitor_name);
3456 printf("environment: %s\n", r->environment);
3457 printf("dll_name: %s\n", r->dll_name);
3460 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3461 TALLOC_CTX *mem_ctx, int argc,
3462 const char **argv)
3464 WERROR werror;
3465 uint32_t count, level = 1, i;
3466 union spoolss_MonitorInfo *info;
3468 /* Parse the command arguments */
3470 if (argc > 2) {
3471 printf("Usage: %s [level]\n", argv[0]);
3472 return WERR_OK;
3475 if (argc == 2) {
3476 level = atoi(argv[1]);
3479 /* Enumerate Print Monitors */
3481 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3482 cli->srv_name_slash,
3483 level,
3485 &count,
3486 &info);
3487 if (!W_ERROR_IS_OK(werror)) {
3488 goto done;
3491 /* Display output */
3493 for (i = 0; i < count; i++) {
3494 switch (level) {
3495 case 1:
3496 display_monitor1(&info[i].info1);
3497 break;
3498 case 2:
3499 display_monitor2(&info[i].info2);
3500 break;
3504 done:
3505 return werror;
3508 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3509 TALLOC_CTX *mem_ctx, int argc,
3510 const char **argv)
3512 WERROR result;
3513 NTSTATUS status;
3514 struct policy_handle handle, gdi_handle;
3515 const char *printername;
3516 struct spoolss_DevmodeContainer devmode_ctr;
3518 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3520 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3521 printername,
3522 SEC_FLAG_MAXIMUM_ALLOWED,
3523 &handle);
3524 if (!W_ERROR_IS_OK(result)) {
3525 return result;
3528 ZERO_STRUCT(devmode_ctr);
3530 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3531 &handle,
3532 &gdi_handle,
3533 &devmode_ctr,
3534 &result);
3535 if (!W_ERROR_IS_OK(result)) {
3536 goto done;
3539 done:
3540 if (is_valid_policy_hnd(&gdi_handle)) {
3541 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3543 if (is_valid_policy_hnd(&handle)) {
3544 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3547 return result;
3550 /* List of commands exported by this module */
3551 struct cmd_set spoolss_commands[] = {
3553 { "SPOOLSS" },
3555 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3556 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3557 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3558 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3559 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3560 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3561 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3562 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3563 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3564 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3565 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3566 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3567 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3568 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3569 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3570 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3571 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3572 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3573 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3574 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3575 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3576 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3577 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3578 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3579 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3580 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3581 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3582 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3583 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3584 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3585 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3586 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3587 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3588 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3589 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3591 { NULL }