s3-waf: Build swat
[Samba/gebeck_regimport.git] / source3 / rpcclient / cmd_spoolss.c
blobb5f34c4b2e99624f81ba613c84f5ad123f87fd7e
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/cli_spoolss.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
30 #include "registry.h"
32 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
33 { \
34 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
35 _cli->srv_name_slash, _arg); \
36 W_ERROR_HAVE_NO_MEMORY(_printername); \
39 /* The version int is used by getdrivers. Note that
40 all architecture strings that support mutliple
41 versions must be grouped together since enumdrivers
42 uses this property to prevent issuing multiple
43 enumdriver calls for the same arch */
46 static const struct print_architecture_table_node archi_table[]= {
48 {"Windows 4.0", "WIN40", 0 },
49 {"Windows NT x86", "W32X86", 2 },
50 {"Windows NT x86", "W32X86", 3 },
51 {"Windows NT R4000", "W32MIPS", 2 },
52 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
53 {"Windows NT PowerPC", "W32PPC", 2 },
54 {"Windows IA64", "IA64", 3 },
55 {"Windows x64", "x64", 3 },
56 {NULL, "", -1 }
59 /**
60 * @file
62 * rpcclient module for SPOOLSS rpc pipe.
64 * This generally just parses and checks command lines, and then calls
65 * a cli_spoolss function.
66 **/
68 /****************************************************************************
69 function to do the mapping between the long architecture name and
70 the short one.
71 ****************************************************************************/
73 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
75 int i=-1;
77 DEBUG(107,("Getting architecture dependant directory\n"));
78 do {
79 i++;
80 } while ( (archi_table[i].long_archi!=NULL ) &&
81 StrCaseCmp(long_archi, archi_table[i].long_archi) );
83 if (archi_table[i].long_archi==NULL) {
84 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
85 return NULL;
88 /* this might be client code - but shouldn't this be an fstrcpy etc? */
91 DEBUGADD(108,("index: [%d]\n", i));
92 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
93 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
95 return archi_table[i].short_archi;
98 /****************************************************************************
99 ****************************************************************************/
101 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
102 TALLOC_CTX *mem_ctx,
103 int argc, const char **argv)
105 WERROR werror;
106 struct policy_handle hnd;
108 if (argc != 2) {
109 printf("Usage: %s <printername>\n", argv[0]);
110 return WERR_OK;
113 if (!cli)
114 return WERR_GENERAL_FAILURE;
116 /* Open the printer handle */
118 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
119 argv[1],
120 PRINTER_ALL_ACCESS,
121 &hnd);
122 if (W_ERROR_IS_OK(werror)) {
123 printf("Printer %s opened successfully\n", argv[1]);
124 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
126 if (!W_ERROR_IS_OK(werror)) {
127 printf("Error closing printer handle! (%s)\n",
128 get_dos_error_msg(werror));
132 return werror;
136 /****************************************************************************
137 ****************************************************************************/
139 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
141 if (!r)
142 return;
144 printf("\tprintername:[%s]\n", r->printername);
145 printf("\tservername:[%s]\n", r->servername);
146 printf("\tcjobs:[0x%x]\n", r->cjobs);
147 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
148 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
149 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
150 r->time.day, r->time.day_of_week);
151 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
152 r->time.second, r->time.millisecond);
154 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
155 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
157 printf("\tversion:[0x%x]\n", r->version);
158 printf("\tfree_build:[0x%x]\n", r->free_build);
159 printf("\tspooling:[0x%x]\n", r->spooling);
160 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
161 printf("\tsession_counter:[0x%x]\n", r->session_counter);
162 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
163 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
164 printf("\tjob_error:[0x%x]\n", r->job_error);
165 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
166 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
167 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
168 printf("\tchange_id:[0x%x]\n", r->change_id);
169 printf("\tlast_error: %s\n", win_errstr(r->last_error));
170 printf("\tstatus:[0x%x]\n", r->status);
171 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
172 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
173 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
174 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
175 printf("\tref_ic:[0x%x]\n", r->ref_ic);
176 printf("\treserved2:[0x%x]\n", r->reserved2);
177 printf("\treserved3:[0x%x]\n", r->reserved3);
179 printf("\n");
182 /****************************************************************************
183 ****************************************************************************/
185 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
187 printf("\tflags:[0x%x]\n", r->flags);
188 printf("\tname:[%s]\n", r->name);
189 printf("\tdescription:[%s]\n", r->description);
190 printf("\tcomment:[%s]\n", r->comment);
192 printf("\n");
195 /****************************************************************************
196 ****************************************************************************/
198 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
200 printf("\tservername:[%s]\n", r->servername);
201 printf("\tprintername:[%s]\n", r->printername);
202 printf("\tsharename:[%s]\n", r->sharename);
203 printf("\tportname:[%s]\n", r->portname);
204 printf("\tdrivername:[%s]\n", r->drivername);
205 printf("\tcomment:[%s]\n", r->comment);
206 printf("\tlocation:[%s]\n", r->location);
207 printf("\tsepfile:[%s]\n", r->sepfile);
208 printf("\tprintprocessor:[%s]\n", r->printprocessor);
209 printf("\tdatatype:[%s]\n", r->datatype);
210 printf("\tparameters:[%s]\n", r->parameters);
211 printf("\tattributes:[0x%x]\n", r->attributes);
212 printf("\tpriority:[0x%x]\n", r->priority);
213 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
214 printf("\tstarttime:[0x%x]\n", r->starttime);
215 printf("\tuntiltime:[0x%x]\n", r->untiltime);
216 printf("\tstatus:[0x%x]\n", r->status);
217 printf("\tcjobs:[0x%x]\n", r->cjobs);
218 printf("\taverageppm:[0x%x]\n", r->averageppm);
220 if (r->secdesc)
221 display_sec_desc(r->secdesc);
223 printf("\n");
226 /****************************************************************************
227 ****************************************************************************/
229 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
231 display_sec_desc(r->secdesc);
233 printf("\n");
236 /****************************************************************************
237 ****************************************************************************/
239 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
241 printf("\tservername:[%s]\n", r->servername);
242 printf("\tprintername:[%s]\n", r->printername);
243 printf("\tattributes:[0x%x]\n", r->attributes);
244 printf("\n");
247 /****************************************************************************
248 ****************************************************************************/
250 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
252 printf("\tprintername:[%s]\n", r->printername);
253 printf("\tportname:[%s]\n", r->portname);
254 printf("\tattributes:[0x%x]\n", r->attributes);
255 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
256 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
257 printf("\n");
260 /****************************************************************************
261 ****************************************************************************/
263 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
265 printf("\tstatus:[0x%x]\n", r->status);
266 printf("\n");
269 /****************************************************************************
270 ****************************************************************************/
272 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
274 printf("\tguid:[%s]\n", r->guid);
275 printf("\taction:[0x%x]\n", r->action);
276 printf("\n");
279 /****************************************************************************
280 ****************************************************************************/
282 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
283 TALLOC_CTX *mem_ctx,
284 int argc, const char **argv)
286 WERROR result;
287 uint32_t level = 1;
288 union spoolss_PrinterInfo *info;
289 uint32_t i, count;
290 const char *name;
291 uint32_t flags = PRINTER_ENUM_LOCAL;
293 if (argc > 4) {
294 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
295 return WERR_OK;
298 if (argc >= 2) {
299 level = atoi(argv[1]);
302 if (argc >= 3) {
303 name = argv[2];
304 } else {
305 name = cli->srv_name_slash;
308 if (argc == 4) {
309 flags = atoi(argv[3]);
312 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
313 flags,
314 name,
315 level,
317 &count,
318 &info);
319 if (W_ERROR_IS_OK(result)) {
321 if (!count) {
322 printf ("No printers returned.\n");
323 goto done;
326 for (i = 0; i < count; i++) {
327 switch (level) {
328 case 0:
329 display_print_info0(&info[i].info0);
330 break;
331 case 1:
332 display_print_info1(&info[i].info1);
333 break;
334 case 2:
335 display_print_info2(&info[i].info2);
336 break;
337 case 3:
338 display_print_info3(&info[i].info3);
339 break;
340 case 4:
341 display_print_info4(&info[i].info4);
342 break;
343 case 5:
344 display_print_info5(&info[i].info5);
345 break;
346 case 6:
347 display_print_info6(&info[i].info6);
348 break;
349 default:
350 printf("unknown info level %d\n", level);
351 goto done;
355 done:
357 return result;
360 /****************************************************************************
361 ****************************************************************************/
363 static void display_port_info_1(struct spoolss_PortInfo1 *r)
365 printf("\tPort Name:\t[%s]\n", r->port_name);
368 /****************************************************************************
369 ****************************************************************************/
371 static void display_port_info_2(struct spoolss_PortInfo2 *r)
373 printf("\tPort Name:\t[%s]\n", r->port_name);
374 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
375 printf("\tDescription:\t[%s]\n", r->description);
376 printf("\tPort Type:\t" );
377 if (r->port_type) {
378 int comma = 0; /* hack */
379 printf( "[" );
380 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
381 printf( "Read" );
382 comma = 1;
384 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
385 printf( "%sWrite", comma ? ", " : "" );
386 comma = 1;
388 /* These two have slightly different interpretations
389 on 95/98/ME but I'm disregarding that for now */
390 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
391 printf( "%sRedirected", comma ? ", " : "" );
392 comma = 1;
394 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
395 printf( "%sNet-Attached", comma ? ", " : "" );
397 printf( "]\n" );
398 } else {
399 printf( "[Unset]\n" );
401 printf("\tReserved:\t[%d]\n", r->reserved);
402 printf("\n");
405 /****************************************************************************
406 ****************************************************************************/
408 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
409 TALLOC_CTX *mem_ctx, int argc,
410 const char **argv)
412 WERROR result;
413 uint32_t level = 1;
414 uint32_t count;
415 union spoolss_PortInfo *info;
417 if (argc > 2) {
418 printf("Usage: %s [level]\n", argv[0]);
419 return WERR_OK;
422 if (argc == 2) {
423 level = atoi(argv[1]);
426 /* Enumerate ports */
428 result = rpccli_spoolss_enumports(cli, mem_ctx,
429 cli->srv_name_slash,
430 level,
432 &count,
433 &info);
434 if (W_ERROR_IS_OK(result)) {
435 int i;
437 for (i = 0; i < count; i++) {
438 switch (level) {
439 case 1:
440 display_port_info_1(&info[i].info1);
441 break;
442 case 2:
443 display_port_info_2(&info[i].info2);
444 break;
445 default:
446 printf("unknown info level %d\n", level);
447 break;
452 return result;
455 /****************************************************************************
456 ****************************************************************************/
458 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
459 TALLOC_CTX *mem_ctx,
460 int argc, const char **argv)
462 struct policy_handle pol;
463 WERROR result;
464 NTSTATUS status;
465 uint32_t info_level = 2;
466 union spoolss_PrinterInfo info;
467 struct spoolss_SetPrinterInfoCtr info_ctr;
468 struct spoolss_SetPrinterInfo2 info2;
469 const char *printername, *comment = NULL;
470 struct spoolss_DevmodeContainer devmode_ctr;
471 struct sec_desc_buf secdesc_ctr;
473 if (argc == 1 || argc > 3) {
474 printf("Usage: %s printername comment\n", argv[0]);
476 return WERR_OK;
479 /* Open a printer handle */
480 if (argc == 3) {
481 comment = argv[2];
484 ZERO_STRUCT(devmode_ctr);
485 ZERO_STRUCT(secdesc_ctr);
487 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
489 /* get a printer handle */
490 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
491 printername,
492 PRINTER_ALL_ACCESS,
493 &pol);
494 if (!W_ERROR_IS_OK(result))
495 goto done;
497 /* Get printer info */
498 result = rpccli_spoolss_getprinter(cli, mem_ctx,
499 &pol,
500 info_level,
502 &info);
503 if (!W_ERROR_IS_OK(result))
504 goto done;
507 /* Modify the comment. */
508 info2.servername = info.info2.servername;
509 info2.printername = info.info2.printername;
510 info2.sharename = info.info2.sharename;
511 info2.portname = info.info2.portname;
512 info2.drivername = info.info2.drivername;
513 info2.comment = comment;
514 info2.location = info.info2.location;
515 info2.devmode_ptr = 0;
516 info2.sepfile = info.info2.sepfile;
517 info2.printprocessor = info.info2.printprocessor;
518 info2.datatype = info.info2.datatype;
519 info2.parameters = info.info2.parameters;
520 info2.secdesc_ptr = 0;
521 info2.attributes = info.info2.attributes;
522 info2.priority = info.info2.priority;
523 info2.defaultpriority = info.info2.defaultpriority;
524 info2.starttime = info.info2.starttime;
525 info2.untiltime = info.info2.untiltime;
526 info2.status = info.info2.status;
527 info2.cjobs = info.info2.cjobs;
528 info2.averageppm = info.info2.averageppm;
530 info_ctr.level = 2;
531 info_ctr.info.info2 = &info2;
533 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
534 &pol,
535 &info_ctr,
536 &devmode_ctr,
537 &secdesc_ctr,
538 0, /* command */
539 &result);
540 if (W_ERROR_IS_OK(result))
541 printf("Success in setting comment.\n");
543 done:
544 if (is_valid_policy_hnd(&pol))
545 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
547 return result;
550 /****************************************************************************
551 ****************************************************************************/
553 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
554 TALLOC_CTX *mem_ctx,
555 int argc, const char **argv)
557 struct policy_handle pol;
558 WERROR result;
559 NTSTATUS status;
560 uint32_t info_level = 2;
561 union spoolss_PrinterInfo info;
562 const char *printername,
563 *new_printername = NULL;
564 struct spoolss_SetPrinterInfoCtr info_ctr;
565 struct spoolss_SetPrinterInfo2 info2;
566 struct spoolss_DevmodeContainer devmode_ctr;
567 struct sec_desc_buf secdesc_ctr;
569 ZERO_STRUCT(devmode_ctr);
570 ZERO_STRUCT(secdesc_ctr);
572 if (argc == 1 || argc > 3) {
573 printf("Usage: %s printername new_printername\n", argv[0]);
575 return WERR_OK;
578 /* Open a printer handle */
579 if (argc == 3) {
580 new_printername = argv[2];
583 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
585 /* get a printer handle */
586 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
587 printername,
588 PRINTER_ALL_ACCESS,
589 &pol);
590 if (!W_ERROR_IS_OK(result))
591 goto done;
593 /* Get printer info */
594 result = rpccli_spoolss_getprinter(cli, mem_ctx,
595 &pol,
596 info_level,
598 &info);
599 if (!W_ERROR_IS_OK(result))
600 goto done;
602 /* Modify the printername. */
603 info2.servername = info.info2.servername;
604 info2.printername = new_printername;
605 info2.sharename = info.info2.sharename;
606 info2.portname = info.info2.portname;
607 info2.drivername = info.info2.drivername;
608 info2.comment = info.info2.comment;
609 info2.location = info.info2.location;
610 info2.devmode_ptr = 0;
611 info2.sepfile = info.info2.sepfile;
612 info2.printprocessor = info.info2.printprocessor;
613 info2.datatype = info.info2.datatype;
614 info2.parameters = info.info2.parameters;
615 info2.secdesc_ptr = 0;
616 info2.attributes = info.info2.attributes;
617 info2.priority = info.info2.priority;
618 info2.defaultpriority = info.info2.defaultpriority;
619 info2.starttime = info.info2.starttime;
620 info2.untiltime = info.info2.untiltime;
621 info2.status = info.info2.status;
622 info2.cjobs = info.info2.cjobs;
623 info2.averageppm = info.info2.averageppm;
625 info_ctr.level = 2;
626 info_ctr.info.info2 = &info2;
628 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
629 &pol,
630 &info_ctr,
631 &devmode_ctr,
632 &secdesc_ctr,
633 0, /* command */
634 &result);
635 if (W_ERROR_IS_OK(result))
636 printf("Success in setting printername.\n");
638 done:
639 if (is_valid_policy_hnd(&pol))
640 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
642 return result;
645 /****************************************************************************
646 ****************************************************************************/
648 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
649 TALLOC_CTX *mem_ctx,
650 int argc, const char **argv)
652 struct policy_handle pol;
653 WERROR result;
654 uint32_t level = 1;
655 const char *printername;
656 union spoolss_PrinterInfo info;
658 if (argc == 1 || argc > 3) {
659 printf("Usage: %s <printername> [level]\n", argv[0]);
660 return WERR_OK;
663 /* Open a printer handle */
664 if (argc == 3) {
665 level = atoi(argv[2]);
668 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
670 /* get a printer handle */
672 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
673 printername,
674 SEC_FLAG_MAXIMUM_ALLOWED,
675 &pol);
676 if (!W_ERROR_IS_OK(result)) {
677 goto done;
680 /* Get printer info */
682 result = rpccli_spoolss_getprinter(cli, mem_ctx,
683 &pol,
684 level,
686 &info);
687 if (!W_ERROR_IS_OK(result)) {
688 goto done;
691 /* Display printer info */
692 switch (level) {
693 case 0:
694 display_print_info0(&info.info0);
695 break;
696 case 1:
697 display_print_info1(&info.info1);
698 break;
699 case 2:
700 display_print_info2(&info.info2);
701 break;
702 case 3:
703 display_print_info3(&info.info3);
704 break;
705 case 4:
706 display_print_info4(&info.info4);
707 break;
708 case 5:
709 display_print_info5(&info.info5);
710 break;
711 case 6:
712 display_print_info6(&info.info6);
713 break;
714 case 7:
715 display_print_info7(&info.info7);
716 break;
717 default:
718 printf("unknown info level %d\n", level);
719 break;
721 done:
722 if (is_valid_policy_hnd(&pol)) {
723 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
726 return result;
729 /****************************************************************************
730 ****************************************************************************/
732 static void display_reg_value(struct regval_blob value)
734 const char *text = NULL;
735 DATA_BLOB blob;
737 switch(value.type) {
738 case REG_DWORD:
739 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
740 *((uint32_t *) value.data_p));
741 break;
742 case REG_SZ:
743 blob = data_blob_const(value.data_p, value.size);
744 pull_reg_sz(talloc_tos(), &blob, &text);
745 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
746 break;
747 case REG_BINARY: {
748 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
749 size_t i, len;
750 printf("%s: REG_BINARY:", value.valuename);
751 len = strlen(hex);
752 for (i=0; i<len; i++) {
753 if (hex[i] == '\0') {
754 break;
756 if (i%40 == 0) {
757 putchar('\n');
759 putchar(hex[i]);
761 TALLOC_FREE(hex);
762 putchar('\n');
763 break;
765 case REG_MULTI_SZ: {
766 uint32_t i;
767 const char **values;
768 blob = data_blob_const(value.data_p, value.size);
770 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
771 d_printf("pull_reg_multi_sz failed\n");
772 break;
775 printf("%s: REG_MULTI_SZ: \n", value.valuename);
776 for (i=0; values[i] != NULL; i++) {
777 d_printf("%s\n", values[i]);
779 TALLOC_FREE(values);
780 break;
782 default:
783 printf("%s: unknown type %d\n", value.valuename, value.type);
788 /****************************************************************************
789 ****************************************************************************/
791 static void display_printer_data(const char *v,
792 enum winreg_Type type,
793 uint8_t *data,
794 uint32_t length)
796 int i;
797 union spoolss_PrinterData r;
798 DATA_BLOB blob = data_blob_const(data, length);
799 WERROR result;
801 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
802 if (!W_ERROR_IS_OK(result)) {
803 return;
806 switch (type) {
807 case REG_DWORD:
808 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
809 break;
810 case REG_SZ:
811 printf("%s: REG_SZ: %s\n", v, r.string);
812 break;
813 case REG_BINARY: {
814 char *hex = hex_encode_talloc(NULL,
815 r.binary.data, r.binary.length);
816 size_t len;
817 printf("%s: REG_BINARY:", v);
818 len = strlen(hex);
819 for (i=0; i<len; i++) {
820 if (hex[i] == '\0') {
821 break;
823 if (i%40 == 0) {
824 putchar('\n');
826 putchar(hex[i]);
828 TALLOC_FREE(hex);
829 putchar('\n');
830 break;
832 case REG_MULTI_SZ:
833 printf("%s: REG_MULTI_SZ: ", v);
834 for (i=0; r.string_array[i] != NULL; i++) {
835 printf("%s ", r.string_array[i]);
837 printf("\n");
838 break;
839 default:
840 printf("%s: unknown type 0x%02x:\n", v, type);
841 break;
845 /****************************************************************************
846 ****************************************************************************/
848 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
849 TALLOC_CTX *mem_ctx,
850 int argc, const char **argv)
852 struct policy_handle pol;
853 WERROR result;
854 fstring printername;
855 const char *valuename;
856 enum winreg_Type type;
857 uint8_t *data;
858 uint32_t needed;
860 if (argc != 3) {
861 printf("Usage: %s <printername> <valuename>\n", argv[0]);
862 printf("<printername> of . queries print server\n");
863 return WERR_OK;
865 valuename = argv[2];
867 /* Open a printer handle */
869 if (strncmp(argv[1], ".", sizeof(".")) == 0)
870 fstrcpy(printername, cli->srv_name_slash);
871 else
872 slprintf(printername, sizeof(printername)-1, "%s\\%s",
873 cli->srv_name_slash, argv[1]);
875 /* get a printer handle */
877 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
878 printername,
879 SEC_FLAG_MAXIMUM_ALLOWED,
880 &pol);
881 if (!W_ERROR_IS_OK(result))
882 goto done;
884 /* Get printer info */
886 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
887 &pol,
888 valuename,
890 &type,
891 &needed,
892 &data);
893 if (!W_ERROR_IS_OK(result))
894 goto done;
896 /* Display printer data */
898 display_printer_data(valuename, type, data, needed);
900 done:
901 if (is_valid_policy_hnd(&pol))
902 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
904 return result;
907 /****************************************************************************
908 ****************************************************************************/
910 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
911 TALLOC_CTX *mem_ctx,
912 int argc, const char **argv)
914 struct policy_handle pol;
915 WERROR result;
916 NTSTATUS status;
917 fstring printername;
918 const char *valuename, *keyname;
920 enum winreg_Type type;
921 uint8_t *data = NULL;
922 uint32_t offered = 0;
923 uint32_t needed;
925 if (argc != 4) {
926 printf("Usage: %s <printername> <keyname> <valuename>\n",
927 argv[0]);
928 printf("<printername> of . queries print server\n");
929 return WERR_OK;
931 valuename = argv[3];
932 keyname = argv[2];
934 /* Open a printer handle */
936 if (strncmp(argv[1], ".", sizeof(".")) == 0)
937 fstrcpy(printername, cli->srv_name_slash);
938 else
939 slprintf(printername, sizeof(printername)-1, "%s\\%s",
940 cli->srv_name_slash, argv[1]);
942 /* get a printer handle */
944 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
945 printername,
946 SEC_FLAG_MAXIMUM_ALLOWED,
947 &pol);
948 if (!W_ERROR_IS_OK(result))
949 goto done;
951 /* Get printer info */
953 data = talloc_zero_array(mem_ctx, uint8_t, offered);
954 if (!data) {
955 goto done;
958 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
959 &pol,
960 keyname,
961 valuename,
962 &type,
963 data,
964 offered,
965 &needed,
966 &result);
967 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
968 offered = needed;
969 data = talloc_zero_array(mem_ctx, uint8_t, offered);
970 if (!data) {
971 goto done;
973 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
974 &pol,
975 keyname,
976 valuename,
977 &type,
978 data,
979 offered,
980 &needed,
981 &result);
984 if (!NT_STATUS_IS_OK(status)) {
985 goto done;
988 if (!W_ERROR_IS_OK(result))
989 goto done;
991 /* Display printer data */
993 display_printer_data(valuename, type, data, needed);
996 done:
997 if (is_valid_policy_hnd(&pol))
998 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1000 return result;
1003 /****************************************************************************
1004 ****************************************************************************/
1006 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1008 if (!r) {
1009 return;
1012 printf("Printer Driver Info 1:\n");
1013 printf("\tDriver Name: [%s]\n", r->driver_name);
1014 printf("\n");
1017 /****************************************************************************
1018 ****************************************************************************/
1020 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1022 if (!r) {
1023 return;
1026 printf("Printer Driver Info 2:\n");
1027 printf("\tVersion: [%x]\n", r->version);
1028 printf("\tDriver Name: [%s]\n", r->driver_name);
1029 printf("\tArchitecture: [%s]\n", r->architecture);
1030 printf("\tDriver Path: [%s]\n", r->driver_path);
1031 printf("\tDatafile: [%s]\n", r->data_file);
1032 printf("\tConfigfile: [%s]\n", r->config_file);
1033 printf("\n");
1036 /****************************************************************************
1037 ****************************************************************************/
1039 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1041 int i;
1043 if (!r) {
1044 return;
1047 printf("Printer Driver Info 3:\n");
1048 printf("\tVersion: [%x]\n", r->version);
1049 printf("\tDriver Name: [%s]\n", r->driver_name);
1050 printf("\tArchitecture: [%s]\n", r->architecture);
1051 printf("\tDriver Path: [%s]\n", r->driver_path);
1052 printf("\tDatafile: [%s]\n", r->data_file);
1053 printf("\tConfigfile: [%s]\n", r->config_file);
1054 printf("\tHelpfile: [%s]\n", r->help_file);
1056 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1057 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1060 printf("\tMonitorname: [%s]\n", r->monitor_name);
1061 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1062 printf("\n");
1065 /****************************************************************************
1066 ****************************************************************************/
1068 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1070 int i;
1072 if (!r) {
1073 return;
1076 printf("Printer Driver Info 4:\n");
1077 printf("\tVersion: [%x]\n", r->version);
1078 printf("\tDriver Name: [%s]\n", r->driver_name);
1079 printf("\tArchitecture: [%s]\n", r->architecture);
1080 printf("\tDriver Path: [%s]\n", r->driver_path);
1081 printf("\tDatafile: [%s]\n", r->data_file);
1082 printf("\tConfigfile: [%s]\n", r->config_file);
1083 printf("\tHelpfile: [%s]\n", r->help_file);
1085 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1086 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1089 printf("\tMonitorname: [%s]\n", r->monitor_name);
1090 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1092 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1093 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1095 printf("\n");
1098 /****************************************************************************
1099 ****************************************************************************/
1101 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1103 if (!r) {
1104 return;
1107 printf("Printer Driver Info 5:\n");
1108 printf("\tVersion: [%x]\n", r->version);
1109 printf("\tDriver Name: [%s]\n", r->driver_name);
1110 printf("\tArchitecture: [%s]\n", r->architecture);
1111 printf("\tDriver Path: [%s]\n", r->driver_path);
1112 printf("\tDatafile: [%s]\n", r->data_file);
1113 printf("\tConfigfile: [%s]\n", r->config_file);
1114 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1115 printf("\tConfig Version: [0x%x]\n", r->config_version);
1116 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1117 printf("\n");
1120 /****************************************************************************
1121 ****************************************************************************/
1123 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1125 int i;
1127 if (!r) {
1128 return;
1131 printf("Printer Driver Info 6:\n");
1132 printf("\tVersion: [%x]\n", r->version);
1133 printf("\tDriver Name: [%s]\n", r->driver_name);
1134 printf("\tArchitecture: [%s]\n", r->architecture);
1135 printf("\tDriver Path: [%s]\n", r->driver_path);
1136 printf("\tDatafile: [%s]\n", r->data_file);
1137 printf("\tConfigfile: [%s]\n", r->config_file);
1138 printf("\tHelpfile: [%s]\n", r->help_file);
1140 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1141 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1144 printf("\tMonitorname: [%s]\n", r->monitor_name);
1145 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1147 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1148 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1151 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1152 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1153 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1154 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1155 printf("\tHardware ID: [%s]\n", r->hardware_id);
1156 printf("\tProvider: [%s]\n", r->provider);
1158 printf("\n");
1161 /****************************************************************************
1162 ****************************************************************************/
1164 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1166 int i;
1168 if (!r) {
1169 return;
1172 printf("Printer Driver Info 8:\n");
1173 printf("\tVersion: [%x]\n", r->version);
1174 printf("\tDriver Name: [%s]\n", r->driver_name);
1175 printf("\tArchitecture: [%s]\n", r->architecture);
1176 printf("\tDriver Path: [%s]\n", r->driver_path);
1177 printf("\tDatafile: [%s]\n", r->data_file);
1178 printf("\tConfigfile: [%s]\n", r->config_file);
1179 printf("\tHelpfile: [%s]\n", r->help_file);
1180 printf("\tMonitorname: [%s]\n", r->monitor_name);
1181 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1183 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1184 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1187 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1188 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1191 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1192 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1193 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1194 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1195 printf("\tHardware ID: [%s]\n", r->hardware_id);
1196 printf("\tProvider: [%s]\n", r->provider);
1197 printf("\tPrint Processor: [%s]\n", r->print_processor);
1198 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1199 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1200 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1202 printf("\tInf Path: [%s]\n", r->inf_path);
1203 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1204 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1205 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1207 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1208 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1209 (long long unsigned int)r->min_inbox_driver_ver_version);
1211 printf("\n");
1214 /****************************************************************************
1215 ****************************************************************************/
1217 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1218 TALLOC_CTX *mem_ctx,
1219 int argc, const char **argv)
1221 struct policy_handle pol;
1222 WERROR werror;
1223 uint32_t level = 3;
1224 const char *printername;
1225 uint32_t i;
1226 bool success = false;
1227 union spoolss_DriverInfo info;
1228 uint32_t server_major_version;
1229 uint32_t server_minor_version;
1231 if ((argc == 1) || (argc > 3)) {
1232 printf("Usage: %s <printername> [level]\n", argv[0]);
1233 return WERR_OK;
1236 /* get the arguments need to open the printer handle */
1238 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1240 if (argc == 3) {
1241 level = atoi(argv[2]);
1244 /* Open a printer handle */
1246 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1247 printername,
1248 PRINTER_ACCESS_USE,
1249 &pol);
1250 if (!W_ERROR_IS_OK(werror)) {
1251 printf("Error opening printer handle for %s!\n", printername);
1252 return werror;
1255 /* loop through and print driver info level for each architecture */
1257 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1259 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1260 &pol,
1261 archi_table[i].long_archi,
1262 level,
1263 0, /* offered */
1264 archi_table[i].version,
1266 &info,
1267 &server_major_version,
1268 &server_minor_version);
1269 if (!W_ERROR_IS_OK(werror)) {
1270 continue;
1273 /* need at least one success */
1275 success = true;
1277 printf("\n[%s]\n", archi_table[i].long_archi);
1279 switch (level) {
1280 case 1:
1281 display_print_driver1(&info.info1);
1282 break;
1283 case 2:
1284 display_print_driver2(&info.info2);
1285 break;
1286 case 3:
1287 display_print_driver3(&info.info3);
1288 break;
1289 case 4:
1290 display_print_driver4(&info.info4);
1291 break;
1292 case 5:
1293 display_print_driver5(&info.info5);
1294 break;
1295 case 6:
1296 display_print_driver6(&info.info6);
1297 break;
1298 case 8:
1299 display_print_driver8(&info.info8);
1300 break;
1301 default:
1302 printf("unknown info level %d\n", level);
1303 break;
1307 /* Cleanup */
1309 if (is_valid_policy_hnd(&pol)) {
1310 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1313 if (success) {
1314 werror = WERR_OK;
1317 return werror;
1320 /****************************************************************************
1321 ****************************************************************************/
1323 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1324 TALLOC_CTX *mem_ctx,
1325 const char *architecture,
1326 uint32_t level)
1328 WERROR werror;
1329 uint32_t count = 0;
1330 union spoolss_DriverInfo *info = NULL;
1331 uint32_t j;
1333 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1334 cli->srv_name_slash,
1335 architecture,
1336 level,
1338 &count,
1339 &info);
1341 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1342 printf("Server does not support environment [%s]\n",
1343 architecture);
1344 return WERR_OK;
1347 if (count == 0) {
1348 return WERR_OK;
1351 if (!W_ERROR_IS_OK(werror)) {
1352 printf("Error getting driver for environment [%s] - %s\n",
1353 architecture, win_errstr(werror));
1354 return werror;
1357 printf("\n[%s]\n", architecture);
1359 switch (level) {
1360 case 1:
1361 for (j=0; j < count; j++) {
1362 display_print_driver1(&info[j].info1);
1364 break;
1365 case 2:
1366 for (j=0; j < count; j++) {
1367 display_print_driver2(&info[j].info2);
1369 break;
1370 case 3:
1371 for (j=0; j < count; j++) {
1372 display_print_driver3(&info[j].info3);
1374 break;
1375 case 4:
1376 for (j=0; j < count; j++) {
1377 display_print_driver4(&info[j].info4);
1379 break;
1380 case 5:
1381 for (j=0; j < count; j++) {
1382 display_print_driver5(&info[j].info5);
1384 break;
1385 case 6:
1386 for (j=0; j < count; j++) {
1387 display_print_driver6(&info[j].info6);
1389 break;
1390 case 8:
1391 for (j=0; j < count; j++) {
1392 display_print_driver8(&info[j].info8);
1394 break;
1395 default:
1396 printf("unknown info level %d\n", level);
1397 return WERR_UNKNOWN_LEVEL;
1400 return werror;
1403 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1404 TALLOC_CTX *mem_ctx,
1405 int argc, const char **argv)
1407 WERROR werror = WERR_OK;
1408 uint32_t level = 1;
1409 uint32_t i;
1410 const char *architecture = NULL;
1412 if (argc > 3) {
1413 printf("Usage: enumdrivers [level] [architecture]\n");
1414 return WERR_OK;
1417 if (argc >= 2) {
1418 level = atoi(argv[1]);
1421 if (argc == 3) {
1422 architecture = argv[2];
1425 if (architecture) {
1426 return enum_driver_by_architecture(cli, mem_ctx,
1427 architecture,
1428 level);
1431 /* loop through and print driver info level for each architecture */
1432 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1433 /* check to see if we already asked for this architecture string */
1435 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1436 continue;
1439 werror = enum_driver_by_architecture(cli, mem_ctx,
1440 archi_table[i].long_archi,
1441 level);
1442 if (!W_ERROR_IS_OK(werror)) {
1443 break;
1447 return werror;
1450 /****************************************************************************
1451 ****************************************************************************/
1453 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1455 printf("\tDirectory Name:[%s]\n", r->directory_name);
1458 /****************************************************************************
1459 ****************************************************************************/
1461 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1462 TALLOC_CTX *mem_ctx,
1463 int argc, const char **argv)
1465 WERROR result;
1466 NTSTATUS status;
1467 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1468 DATA_BLOB buffer;
1469 uint32_t offered;
1470 union spoolss_DriverDirectoryInfo info;
1471 uint32_t needed;
1473 if (argc > 2) {
1474 printf("Usage: %s [environment]\n", argv[0]);
1475 return WERR_OK;
1478 /* Get the arguments need to open the printer handle */
1480 if (argc == 2) {
1481 env = argv[1];
1484 /* Get the directory. Only use Info level 1 */
1486 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1487 cli->srv_name_slash,
1488 env,
1490 NULL, /* buffer */
1491 0, /* offered */
1492 NULL, /* info */
1493 &needed,
1494 &result);
1495 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1496 offered = needed;
1497 buffer = data_blob_talloc_zero(mem_ctx, needed);
1499 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1500 cli->srv_name_slash,
1501 env,
1503 &buffer,
1504 offered,
1505 &info,
1506 &needed,
1507 &result);
1510 if (W_ERROR_IS_OK(result)) {
1511 display_printdriverdir_1(&info.info1);
1514 return result;
1517 /****************************************************************************
1518 ****************************************************************************/
1520 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1521 struct spoolss_AddDriverInfo3 *info,
1522 const char *arch)
1525 int i;
1527 for (i=0; archi_table[i].long_archi != NULL; i++)
1529 if (strcmp(arch, archi_table[i].short_archi) == 0)
1531 info->version = archi_table[i].version;
1532 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1533 break;
1537 if (archi_table[i].long_archi == NULL)
1539 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1542 return;
1546 /**************************************************************************
1547 wrapper for strtok to get the next parameter from a delimited list.
1548 Needed to handle the empty parameter string denoted by "NULL"
1549 *************************************************************************/
1551 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1552 const char *delim, const char **dest,
1553 char **saveptr)
1555 char *ptr;
1557 /* get the next token */
1558 ptr = strtok_r(str, delim, saveptr);
1560 /* a string of 'NULL' is used to represent an empty
1561 parameter because two consecutive delimiters
1562 will not return an empty string. See man strtok(3)
1563 for details */
1564 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1565 ptr = NULL;
1568 if (dest != NULL) {
1569 *dest = talloc_strdup(mem_ctx, ptr);
1572 return ptr;
1575 /********************************************************************************
1576 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1577 string in the form of
1578 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1579 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1580 <Default Data Type>:<Comma Separated list of Files>
1581 *******************************************************************************/
1583 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1584 char *args)
1586 char *str, *str2;
1587 int count = 0;
1588 char *saveptr = NULL;
1589 struct spoolss_StringArray *deps;
1590 const char **file_array = NULL;
1591 int i;
1593 /* fill in the UNISTR fields */
1594 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1595 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1596 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1597 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1598 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1599 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1600 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1602 /* <Comma Separated List of Dependent Files> */
1603 /* save the beginning of the string */
1604 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1605 str = str2;
1607 /* begin to strip out each filename */
1608 str = strtok_r(str, ",", &saveptr);
1610 /* no dependent files, we are done */
1611 if (!str) {
1612 return true;
1615 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1616 if (!deps) {
1617 return false;
1620 while (str != NULL) {
1621 add_string_to_array(deps, str, &file_array, &count);
1622 str = strtok_r(NULL, ",", &saveptr);
1625 deps->string = talloc_zero_array(deps, const char *, count + 1);
1626 if (!deps->string) {
1627 return false;
1630 for (i=0; i < count; i++) {
1631 deps->string[i] = file_array[i];
1634 r->dependent_files = deps;
1636 return true;
1639 /****************************************************************************
1640 ****************************************************************************/
1642 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1643 TALLOC_CTX *mem_ctx,
1644 int argc, const char **argv)
1646 WERROR result;
1647 NTSTATUS status;
1648 uint32_t level = 3;
1649 struct spoolss_AddDriverInfoCtr info_ctr;
1650 struct spoolss_AddDriverInfo3 info3;
1651 const char *arch;
1652 char *driver_args;
1654 /* parse the command arguments */
1655 if (argc != 3 && argc != 4)
1657 printf ("Usage: %s <Environment> \\\n", argv[0]);
1658 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1659 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1660 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1661 printf ("\t[version]\n");
1663 return WERR_OK;
1666 /* Fill in the spoolss_AddDriverInfo3 struct */
1667 ZERO_STRUCT(info3);
1669 arch = cmd_spoolss_get_short_archi(argv[1]);
1670 if (!arch) {
1671 printf ("Error Unknown architechture [%s]\n", argv[1]);
1672 return WERR_INVALID_PARAM;
1675 set_drv_info_3_env(mem_ctx, &info3, arch);
1677 driver_args = talloc_strdup( mem_ctx, argv[2] );
1678 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1680 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1681 return WERR_INVALID_PARAM;
1684 /* if printer driver version specified, override the default version
1685 * used by the architecture. This allows installation of Windows
1686 * 2000 (version 3) printer drivers. */
1687 if (argc == 4)
1689 info3.version = atoi(argv[3]);
1693 info_ctr.level = level;
1694 info_ctr.info.info3 = &info3;
1696 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1697 cli->srv_name_slash,
1698 &info_ctr,
1699 &result);
1700 if (!NT_STATUS_IS_OK(status)) {
1701 return ntstatus_to_werror(status);
1703 if (W_ERROR_IS_OK(result)) {
1704 printf ("Printer Driver %s successfully installed.\n",
1705 info3.driver_name);
1708 return result;
1712 /****************************************************************************
1713 ****************************************************************************/
1715 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1716 TALLOC_CTX *mem_ctx,
1717 int argc, const char **argv)
1719 WERROR result;
1720 struct spoolss_SetPrinterInfoCtr info_ctr;
1721 struct spoolss_SetPrinterInfo2 info2;
1723 /* parse the command arguments */
1724 if (argc != 5)
1726 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1727 return WERR_OK;
1730 /* Fill in the DRIVER_INFO_2 struct */
1731 ZERO_STRUCT(info2);
1733 info2.printername = argv[1];
1734 info2.drivername = argv[3];
1735 info2.sharename = argv[2];
1736 info2.portname = argv[4];
1737 info2.comment = "Created by rpcclient";
1738 info2.printprocessor = "winprint";
1739 info2.datatype = "RAW";
1740 info2.devmode_ptr = 0;
1741 info2.secdesc_ptr = 0;
1742 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1743 info2.priority = 0;
1744 info2.defaultpriority = 0;
1745 info2.starttime = 0;
1746 info2.untiltime = 0;
1748 /* These three fields must not be used by AddPrinter()
1749 as defined in the MS Platform SDK documentation..
1750 --jerry
1751 info2.status = 0;
1752 info2.cjobs = 0;
1753 info2.averageppm = 0;
1756 info_ctr.level = 2;
1757 info_ctr.info.info2 = &info2;
1759 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1760 &info_ctr);
1761 if (W_ERROR_IS_OK(result))
1762 printf ("Printer %s successfully installed.\n", argv[1]);
1764 return result;
1767 /****************************************************************************
1768 ****************************************************************************/
1770 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1771 TALLOC_CTX *mem_ctx,
1772 int argc, const char **argv)
1774 struct policy_handle pol;
1775 WERROR result;
1776 NTSTATUS status;
1777 uint32_t level = 2;
1778 const char *printername;
1779 union spoolss_PrinterInfo info;
1780 struct spoolss_SetPrinterInfoCtr info_ctr;
1781 struct spoolss_SetPrinterInfo2 info2;
1782 struct spoolss_DevmodeContainer devmode_ctr;
1783 struct sec_desc_buf secdesc_ctr;
1785 ZERO_STRUCT(devmode_ctr);
1786 ZERO_STRUCT(secdesc_ctr);
1788 /* parse the command arguments */
1789 if (argc != 3)
1791 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1792 return WERR_OK;
1795 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1797 /* Get a printer handle */
1799 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1800 printername,
1801 PRINTER_ALL_ACCESS,
1802 &pol);
1803 if (!W_ERROR_IS_OK(result))
1804 goto done;
1806 /* Get printer info */
1808 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1809 &pol,
1810 level,
1812 &info);
1813 if (!W_ERROR_IS_OK(result)) {
1814 printf ("Unable to retrieve printer information!\n");
1815 goto done;
1818 /* Set the printer driver */
1820 info2.servername = info.info2.servername;
1821 info2.printername = info.info2.printername;
1822 info2.sharename = info.info2.sharename;
1823 info2.portname = info.info2.portname;
1824 info2.drivername = argv[2];
1825 info2.comment = info.info2.comment;
1826 info2.location = info.info2.location;
1827 info2.devmode_ptr = 0;
1828 info2.sepfile = info.info2.sepfile;
1829 info2.printprocessor = info.info2.printprocessor;
1830 info2.datatype = info.info2.datatype;
1831 info2.parameters = info.info2.parameters;
1832 info2.secdesc_ptr = 0;
1833 info2.attributes = info.info2.attributes;
1834 info2.priority = info.info2.priority;
1835 info2.defaultpriority = info.info2.defaultpriority;
1836 info2.starttime = info.info2.starttime;
1837 info2.untiltime = info.info2.untiltime;
1838 info2.status = info.info2.status;
1839 info2.cjobs = info.info2.cjobs;
1840 info2.averageppm = info.info2.averageppm;
1842 info_ctr.level = 2;
1843 info_ctr.info.info2 = &info2;
1845 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1846 &pol,
1847 &info_ctr,
1848 &devmode_ctr,
1849 &secdesc_ctr,
1850 0, /* command */
1851 &result);
1852 if (!W_ERROR_IS_OK(result)) {
1853 printf("SetPrinter call failed!\n");
1854 goto done;;
1857 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1859 done:
1860 /* Cleanup */
1862 if (is_valid_policy_hnd(&pol))
1863 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1865 return result;
1869 /****************************************************************************
1870 ****************************************************************************/
1872 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1873 TALLOC_CTX *mem_ctx,
1874 int argc, const char **argv)
1876 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1877 NTSTATUS status;
1879 int i;
1880 int vers = -1;
1882 const char *arch = NULL;
1883 uint32_t delete_flags = 0;
1885 /* parse the command arguments */
1886 if (argc < 2 || argc > 4) {
1887 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1888 return WERR_OK;
1891 if (argc >= 3)
1892 arch = argv[2];
1893 if (argc == 4)
1894 vers = atoi (argv[3]);
1896 if (vers >= 0) {
1897 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1900 /* delete the driver for all architectures */
1901 for (i=0; archi_table[i].long_archi; i++) {
1903 if (arch && !strequal( archi_table[i].long_archi, arch))
1904 continue;
1906 if (vers >= 0 && archi_table[i].version != vers)
1907 continue;
1909 /* make the call to remove the driver */
1910 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1911 cli->srv_name_slash,
1912 archi_table[i].long_archi,
1913 argv[1],
1914 delete_flags,
1915 archi_table[i].version,
1916 &result);
1918 if ( !W_ERROR_IS_OK(result) )
1920 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1921 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1922 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1925 else
1927 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1928 archi_table[i].long_archi, archi_table[i].version);
1929 ret = WERR_OK;
1933 return ret;
1937 /****************************************************************************
1938 ****************************************************************************/
1940 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1941 TALLOC_CTX *mem_ctx,
1942 int argc, const char **argv)
1944 WERROR result = WERR_OK;
1945 NTSTATUS status;
1946 int i;
1948 /* parse the command arguments */
1949 if (argc != 2) {
1950 printf ("Usage: %s <driver>\n", argv[0]);
1951 return WERR_OK;
1954 /* delete the driver for all architectures */
1955 for (i=0; archi_table[i].long_archi; i++) {
1956 /* make the call to remove the driver */
1957 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1958 cli->srv_name_slash,
1959 archi_table[i].long_archi,
1960 argv[1],
1961 &result);
1962 if (!NT_STATUS_IS_OK(status)) {
1963 return result;
1965 if ( !W_ERROR_IS_OK(result) ) {
1966 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1967 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1968 argv[1], archi_table[i].long_archi,
1969 W_ERROR_V(result));
1971 } else {
1972 printf ("Driver %s removed for arch [%s].\n", argv[1],
1973 archi_table[i].long_archi);
1977 return result;
1980 /****************************************************************************
1981 ****************************************************************************/
1983 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1984 TALLOC_CTX *mem_ctx,
1985 int argc, const char **argv)
1987 WERROR result;
1988 NTSTATUS status;
1989 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1990 DATA_BLOB buffer;
1991 uint32_t offered;
1992 union spoolss_PrintProcessorDirectoryInfo info;
1993 uint32_t needed;
1995 /* parse the command arguments */
1996 if (argc > 2) {
1997 printf ("Usage: %s [environment]\n", argv[0]);
1998 return WERR_OK;
2001 if (argc == 2) {
2002 environment = argv[1];
2005 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2006 cli->srv_name_slash,
2007 environment,
2009 NULL, /* buffer */
2010 0, /* offered */
2011 NULL, /* info */
2012 &needed,
2013 &result);
2014 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2015 offered = needed;
2016 buffer = data_blob_talloc_zero(mem_ctx, needed);
2018 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2019 cli->srv_name_slash,
2020 environment,
2022 &buffer,
2023 offered,
2024 &info,
2025 &needed,
2026 &result);
2029 if (W_ERROR_IS_OK(result)) {
2030 printf("%s\n", info.info1.directory_name);
2033 return result;
2036 /****************************************************************************
2037 ****************************************************************************/
2039 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2040 int argc, const char **argv)
2042 struct policy_handle handle;
2043 WERROR werror;
2044 NTSTATUS status;
2045 const char *printername;
2046 union spoolss_AddFormInfo info;
2047 struct spoolss_AddFormInfo1 info1;
2048 struct spoolss_AddFormInfo2 info2;
2049 uint32_t level = 1;
2051 /* Parse the command arguments */
2053 if (argc < 3 || argc > 5) {
2054 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2055 return WERR_OK;
2058 /* Get a printer handle */
2060 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2062 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2063 printername,
2064 PRINTER_ALL_ACCESS,
2065 &handle);
2066 if (!W_ERROR_IS_OK(werror))
2067 goto done;
2069 /* Dummy up some values for the form data */
2071 if (argc == 4) {
2072 level = atoi(argv[3]);
2075 switch (level) {
2076 case 1:
2077 info1.flags = SPOOLSS_FORM_USER;
2078 info1.form_name = argv[2];
2079 info1.size.width = 100;
2080 info1.size.height = 100;
2081 info1.area.left = 0;
2082 info1.area.top = 10;
2083 info1.area.right = 20;
2084 info1.area.bottom = 30;
2086 info.info1 = &info1;
2088 break;
2089 case 2:
2090 info2.flags = SPOOLSS_FORM_USER;
2091 info2.form_name = argv[2];
2092 info2.size.width = 100;
2093 info2.size.height = 100;
2094 info2.area.left = 0;
2095 info2.area.top = 10;
2096 info2.area.right = 20;
2097 info2.area.bottom = 30;
2098 info2.keyword = argv[2];
2099 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2100 info2.mui_dll = NULL;
2101 info2.ressource_id = 0;
2102 info2.display_name = argv[2];
2103 info2.lang_id = 0;
2105 info.info2 = &info2;
2107 break;
2110 /* Add the form */
2113 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2114 &handle,
2115 level,
2116 info,
2117 &werror);
2119 done:
2120 if (is_valid_policy_hnd(&handle))
2121 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2123 return werror;
2126 /****************************************************************************
2127 ****************************************************************************/
2129 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2130 int argc, const char **argv)
2132 struct policy_handle handle;
2133 WERROR werror;
2134 NTSTATUS status;
2135 const char *printername;
2136 union spoolss_AddFormInfo info;
2137 struct spoolss_AddFormInfo1 info1;
2139 /* Parse the command arguments */
2141 if (argc != 3) {
2142 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2143 return WERR_OK;
2146 /* Get a printer handle */
2148 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2150 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2151 printername,
2152 SEC_FLAG_MAXIMUM_ALLOWED,
2153 &handle);
2154 if (!W_ERROR_IS_OK(werror))
2155 goto done;
2157 /* Dummy up some values for the form data */
2159 info1.flags = SPOOLSS_FORM_PRINTER;
2160 info1.size.width = 100;
2161 info1.size.height = 100;
2162 info1.area.left = 0;
2163 info1.area.top = 1000;
2164 info1.area.right = 2000;
2165 info1.area.bottom = 3000;
2166 info1.form_name = argv[2];
2168 info.info1 = &info1;
2170 /* Set the form */
2172 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2173 &handle,
2174 argv[2],
2176 info,
2177 &werror);
2179 done:
2180 if (is_valid_policy_hnd(&handle))
2181 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2183 return werror;
2186 /****************************************************************************
2187 ****************************************************************************/
2189 static const char *get_form_flag(int form_flag)
2191 switch (form_flag) {
2192 case SPOOLSS_FORM_USER:
2193 return "FORM_USER";
2194 case SPOOLSS_FORM_BUILTIN:
2195 return "FORM_BUILTIN";
2196 case SPOOLSS_FORM_PRINTER:
2197 return "FORM_PRINTER";
2198 default:
2199 return "unknown";
2203 /****************************************************************************
2204 ****************************************************************************/
2206 static void display_form_info1(struct spoolss_FormInfo1 *r)
2208 printf("%s\n" \
2209 "\tflag: %s (%d)\n" \
2210 "\twidth: %d, length: %d\n" \
2211 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2212 r->form_name, get_form_flag(r->flags), r->flags,
2213 r->size.width, r->size.height,
2214 r->area.left, r->area.right,
2215 r->area.top, r->area.bottom);
2218 /****************************************************************************
2219 ****************************************************************************/
2221 static void display_form_info2(struct spoolss_FormInfo2 *r)
2223 printf("%s\n" \
2224 "\tflag: %s (%d)\n" \
2225 "\twidth: %d, length: %d\n" \
2226 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2227 r->form_name, get_form_flag(r->flags), r->flags,
2228 r->size.width, r->size.height,
2229 r->area.left, r->area.right,
2230 r->area.top, r->area.bottom);
2231 printf("\tkeyword: %s\n", r->keyword);
2232 printf("\tstring_type: 0x%08x\n", r->string_type);
2233 printf("\tmui_dll: %s\n", r->mui_dll);
2234 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2235 printf("\tdisplay_name: %s\n", r->display_name);
2236 printf("\tlang_id: %d\n", r->lang_id);
2237 printf("\n");
2240 /****************************************************************************
2241 ****************************************************************************/
2243 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2244 int argc, const char **argv)
2246 struct policy_handle handle;
2247 WERROR werror;
2248 NTSTATUS status;
2249 const char *printername;
2250 DATA_BLOB buffer;
2251 uint32_t offered = 0;
2252 union spoolss_FormInfo info;
2253 uint32_t needed;
2254 uint32_t level = 1;
2256 /* Parse the command arguments */
2258 if (argc < 3 || argc > 5) {
2259 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2260 return WERR_OK;
2263 /* Get a printer handle */
2265 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2267 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2268 printername,
2269 SEC_FLAG_MAXIMUM_ALLOWED,
2270 &handle);
2271 if (!W_ERROR_IS_OK(werror))
2272 goto done;
2274 if (argc == 4) {
2275 level = atoi(argv[3]);
2278 /* Get the form */
2280 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2281 &handle,
2282 argv[2],
2283 level,
2284 NULL,
2285 offered,
2286 &info,
2287 &needed,
2288 &werror);
2289 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2290 buffer = data_blob_talloc_zero(mem_ctx, needed);
2291 offered = needed;
2292 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2293 &handle,
2294 argv[2],
2295 level,
2296 &buffer,
2297 offered,
2298 &info,
2299 &needed,
2300 &werror);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 return werror;
2307 switch (level) {
2308 case 1:
2309 display_form_info1(&info.info1);
2310 break;
2311 case 2:
2312 display_form_info2(&info.info2);
2313 break;
2316 done:
2317 if (is_valid_policy_hnd(&handle))
2318 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2320 return werror;
2323 /****************************************************************************
2324 ****************************************************************************/
2326 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2327 TALLOC_CTX *mem_ctx, int argc,
2328 const char **argv)
2330 struct policy_handle handle;
2331 WERROR werror;
2332 NTSTATUS status;
2333 const char *printername;
2335 /* Parse the command arguments */
2337 if (argc != 3) {
2338 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2339 return WERR_OK;
2342 /* Get a printer handle */
2344 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2346 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2347 printername,
2348 SEC_FLAG_MAXIMUM_ALLOWED,
2349 &handle);
2350 if (!W_ERROR_IS_OK(werror))
2351 goto done;
2353 /* Delete the form */
2355 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2356 &handle,
2357 argv[2],
2358 &werror);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 return ntstatus_to_werror(status);
2363 done:
2364 if (is_valid_policy_hnd(&handle))
2365 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2367 return werror;
2370 /****************************************************************************
2371 ****************************************************************************/
2373 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2374 TALLOC_CTX *mem_ctx, int argc,
2375 const char **argv)
2377 struct policy_handle handle;
2378 WERROR werror;
2379 const char *printername;
2380 uint32_t num_forms, level = 1, i;
2381 union spoolss_FormInfo *forms;
2383 /* Parse the command arguments */
2385 if (argc < 2 || argc > 4) {
2386 printf ("Usage: %s <printer> [level]\n", argv[0]);
2387 return WERR_OK;
2390 /* Get a printer handle */
2392 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2394 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2395 printername,
2396 SEC_FLAG_MAXIMUM_ALLOWED,
2397 &handle);
2398 if (!W_ERROR_IS_OK(werror))
2399 goto done;
2401 if (argc == 3) {
2402 level = atoi(argv[2]);
2405 /* Enumerate forms */
2407 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2408 &handle,
2409 level,
2411 &num_forms,
2412 &forms);
2414 if (!W_ERROR_IS_OK(werror))
2415 goto done;
2417 /* Display output */
2419 for (i = 0; i < num_forms; i++) {
2420 switch (level) {
2421 case 1:
2422 display_form_info1(&forms[i].info1);
2423 break;
2424 case 2:
2425 display_form_info2(&forms[i].info2);
2426 break;
2430 done:
2431 if (is_valid_policy_hnd(&handle))
2432 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2434 return werror;
2437 /****************************************************************************
2438 ****************************************************************************/
2440 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2441 TALLOC_CTX *mem_ctx,
2442 int argc, const char **argv)
2444 WERROR result;
2445 NTSTATUS status;
2446 const char *printername;
2447 struct policy_handle pol;
2448 union spoolss_PrinterInfo info;
2449 enum winreg_Type type;
2450 union spoolss_PrinterData data;
2451 DATA_BLOB blob;
2453 /* parse the command arguments */
2454 if (argc < 5) {
2455 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2456 " <value> <data>\n",
2457 argv[0]);
2458 return WERR_OK;
2461 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2463 type = REG_NONE;
2465 if (strequal(argv[2], "string")) {
2466 type = REG_SZ;
2469 if (strequal(argv[2], "binary")) {
2470 type = REG_BINARY;
2473 if (strequal(argv[2], "dword")) {
2474 type = REG_DWORD;
2477 if (strequal(argv[2], "multistring")) {
2478 type = REG_MULTI_SZ;
2481 if (type == REG_NONE) {
2482 printf("Unknown data type: %s\n", argv[2]);
2483 result = WERR_INVALID_PARAM;
2484 goto done;
2487 /* get a printer handle */
2489 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2490 printername,
2491 SEC_FLAG_MAXIMUM_ALLOWED,
2492 &pol);
2493 if (!W_ERROR_IS_OK(result)) {
2494 goto done;
2497 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2498 &pol,
2501 &info);
2502 if (!W_ERROR_IS_OK(result)) {
2503 goto done;
2506 printf("%s\n", current_timestring(mem_ctx, true));
2507 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2509 /* Set the printer data */
2511 switch (type) {
2512 case REG_SZ:
2513 data.string = talloc_strdup(mem_ctx, argv[4]);
2514 W_ERROR_HAVE_NO_MEMORY(data.string);
2515 break;
2516 case REG_DWORD:
2517 data.value = strtoul(argv[4], NULL, 10);
2518 break;
2519 case REG_BINARY:
2520 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2521 break;
2522 case REG_MULTI_SZ: {
2523 int i, num_strings;
2524 const char **strings = NULL;
2526 for (i=4; i<argc; i++) {
2527 if (strcmp(argv[i], "NULL") == 0) {
2528 argv[i] = "";
2530 if (!add_string_to_array(mem_ctx, argv[i],
2531 &strings,
2532 &num_strings)) {
2533 result = WERR_NOMEM;
2534 goto done;
2537 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2538 if (!data.string_array) {
2539 result = WERR_NOMEM;
2540 goto done;
2542 for (i=0; i < num_strings; i++) {
2543 data.string_array[i] = strings[i];
2545 break;
2547 default:
2548 printf("Unknown data type: %s\n", argv[2]);
2549 result = WERR_INVALID_PARAM;
2550 goto done;
2553 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2554 if (!W_ERROR_IS_OK(result)) {
2555 goto done;
2558 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2559 &pol,
2560 argv[3], /* value_name */
2561 type,
2562 blob.data,
2563 blob.length,
2564 &result);
2565 if (!W_ERROR_IS_OK(result)) {
2566 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2567 goto done;
2569 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2571 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2572 &pol,
2575 &info);
2576 if (!W_ERROR_IS_OK(result)) {
2577 goto done;
2580 printf("%s\n", current_timestring(mem_ctx, true));
2581 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2583 done:
2584 /* cleanup */
2585 if (is_valid_policy_hnd(&pol)) {
2586 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2589 return result;
2592 /****************************************************************************
2593 ****************************************************************************/
2595 static void display_job_info1(struct spoolss_JobInfo1 *r)
2597 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2598 r->user_name, r->document_name, r->text_status, r->pages_printed,
2599 r->total_pages);
2602 /****************************************************************************
2603 ****************************************************************************/
2605 static void display_job_info2(struct spoolss_JobInfo2 *r)
2607 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2608 r->position, r->job_id,
2609 r->user_name, r->document_name, r->text_status, r->pages_printed,
2610 r->total_pages, r->size);
2613 /****************************************************************************
2614 ****************************************************************************/
2616 static void display_job_info3(struct spoolss_JobInfo3 *r)
2618 printf("jobid[%d], next_jobid[%d]\n",
2619 r->job_id, r->next_job_id);
2622 /****************************************************************************
2623 ****************************************************************************/
2625 static void display_job_info4(struct spoolss_JobInfo4 *r)
2627 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2628 r->position, r->job_id,
2629 r->user_name, r->document_name, r->text_status, r->pages_printed,
2630 r->total_pages, r->size, r->size_high);
2633 /****************************************************************************
2634 ****************************************************************************/
2636 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2637 TALLOC_CTX *mem_ctx, int argc,
2638 const char **argv)
2640 WERROR result;
2641 uint32_t level = 1, count, i;
2642 const char *printername;
2643 struct policy_handle hnd;
2644 union spoolss_JobInfo *info;
2646 if (argc < 2 || argc > 3) {
2647 printf("Usage: %s printername [level]\n", argv[0]);
2648 return WERR_OK;
2651 if (argc == 3) {
2652 level = atoi(argv[2]);
2655 /* Open printer handle */
2657 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2659 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2660 printername,
2661 SEC_FLAG_MAXIMUM_ALLOWED,
2662 &hnd);
2663 if (!W_ERROR_IS_OK(result))
2664 goto done;
2666 /* Enumerate ports */
2668 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2669 &hnd,
2670 0, /* firstjob */
2671 1000, /* numjobs */
2672 level,
2674 &count,
2675 &info);
2676 if (!W_ERROR_IS_OK(result)) {
2677 goto done;
2680 for (i = 0; i < count; i++) {
2681 switch (level) {
2682 case 1:
2683 display_job_info1(&info[i].info1);
2684 break;
2685 case 2:
2686 display_job_info2(&info[i].info2);
2687 break;
2688 default:
2689 d_printf("unknown info level %d\n", level);
2690 break;
2694 done:
2695 if (is_valid_policy_hnd(&hnd)) {
2696 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2699 return result;
2702 /****************************************************************************
2703 ****************************************************************************/
2705 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2706 TALLOC_CTX *mem_ctx, int argc,
2707 const char **argv)
2709 WERROR result;
2710 const char *printername;
2711 struct policy_handle hnd;
2712 uint32_t job_id;
2713 uint32_t level = 1;
2714 union spoolss_JobInfo info;
2716 if (argc < 3 || argc > 4) {
2717 printf("Usage: %s printername job_id [level]\n", argv[0]);
2718 return WERR_OK;
2721 job_id = atoi(argv[2]);
2723 if (argc == 4) {
2724 level = atoi(argv[3]);
2727 /* Open printer handle */
2729 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2731 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2732 printername,
2733 SEC_FLAG_MAXIMUM_ALLOWED,
2734 &hnd);
2735 if (!W_ERROR_IS_OK(result)) {
2736 goto done;
2739 /* Enumerate ports */
2741 result = rpccli_spoolss_getjob(cli, mem_ctx,
2742 &hnd,
2743 job_id,
2744 level,
2746 &info);
2748 if (!W_ERROR_IS_OK(result)) {
2749 goto done;
2752 switch (level) {
2753 case 1:
2754 display_job_info1(&info.info1);
2755 break;
2756 case 2:
2757 display_job_info2(&info.info2);
2758 break;
2759 case 3:
2760 display_job_info3(&info.info3);
2761 break;
2762 case 4:
2763 display_job_info4(&info.info4);
2764 break;
2765 default:
2766 d_printf("unknown info level %d\n", level);
2767 break;
2770 done:
2771 if (is_valid_policy_hnd(&hnd)) {
2772 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2775 return result;
2778 /****************************************************************************
2779 ****************************************************************************/
2781 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2782 TALLOC_CTX *mem_ctx, int argc,
2783 const char **argv)
2785 WERROR result;
2786 NTSTATUS status;
2787 const char *printername;
2788 struct policy_handle hnd;
2789 uint32_t job_id;
2790 enum spoolss_JobControl command;
2792 if (argc != 4) {
2793 printf("Usage: %s printername job_id command\n", argv[0]);
2794 return WERR_OK;
2797 job_id = atoi(argv[2]);
2798 command = atoi(argv[3]);
2800 /* Open printer handle */
2802 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2804 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2805 printername,
2806 SEC_FLAG_MAXIMUM_ALLOWED,
2807 &hnd);
2808 if (!W_ERROR_IS_OK(result)) {
2809 goto done;
2812 /* Set Job */
2814 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2815 &hnd,
2816 job_id,
2817 NULL,
2818 command,
2819 &result);
2821 if (!W_ERROR_IS_OK(result)) {
2822 goto done;
2825 done:
2826 if (is_valid_policy_hnd(&hnd)) {
2827 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2830 return result;
2833 /****************************************************************************
2834 ****************************************************************************/
2836 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2837 TALLOC_CTX *mem_ctx, int argc,
2838 const char **argv)
2840 WERROR result;
2841 NTSTATUS status;
2842 uint32_t i = 0;
2843 const char *printername;
2844 struct policy_handle hnd;
2845 uint32_t value_offered = 0;
2846 const char *value_name = NULL;
2847 uint32_t value_needed;
2848 enum winreg_Type type;
2849 uint8_t *data = NULL;
2850 uint32_t data_offered = 0;
2851 uint32_t data_needed;
2853 if (argc != 2) {
2854 printf("Usage: %s printername\n", argv[0]);
2855 return WERR_OK;
2858 /* Open printer handle */
2860 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2862 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2863 printername,
2864 SEC_FLAG_MAXIMUM_ALLOWED,
2865 &hnd);
2866 if (!W_ERROR_IS_OK(result)) {
2867 goto done;
2870 /* Enumerate data */
2872 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2873 &hnd,
2875 value_name,
2876 value_offered,
2877 &value_needed,
2878 &type,
2879 data,
2880 data_offered,
2881 &data_needed,
2882 &result);
2884 data_offered = data_needed;
2885 value_offered = value_needed;
2886 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2887 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2889 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2891 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2892 &hnd,
2893 i++,
2894 value_name,
2895 value_offered,
2896 &value_needed,
2897 &type,
2898 data,
2899 data_offered,
2900 &data_needed,
2901 &result);
2902 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2903 struct regval_blob v;
2904 fstrcpy(v.valuename, value_name);
2905 v.type = type;
2906 v.size = data_offered;
2907 v.data_p = data;
2908 display_reg_value(v);
2912 if (W_ERROR_V(result) == ERRnomoreitems) {
2913 result = W_ERROR(ERRsuccess);
2916 done:
2917 if (is_valid_policy_hnd(&hnd)) {
2918 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2921 return result;
2924 /****************************************************************************
2925 ****************************************************************************/
2927 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2928 TALLOC_CTX *mem_ctx, int argc,
2929 const char **argv)
2931 WERROR result;
2932 uint32_t i;
2933 const char *printername;
2934 struct policy_handle hnd;
2935 uint32_t count;
2936 struct spoolss_PrinterEnumValues *info;
2938 if (argc != 3) {
2939 printf("Usage: %s printername <keyname>\n", argv[0]);
2940 return WERR_OK;
2943 /* Open printer handle */
2945 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2947 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2948 printername,
2949 SEC_FLAG_MAXIMUM_ALLOWED,
2950 &hnd);
2951 if (!W_ERROR_IS_OK(result)) {
2952 goto done;
2955 /* Enumerate subkeys */
2957 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2958 &hnd,
2959 argv[2],
2961 &count,
2962 &info);
2963 if (!W_ERROR_IS_OK(result)) {
2964 goto done;
2967 for (i=0; i < count; i++) {
2968 display_printer_data(info[i].value_name,
2969 info[i].type,
2970 info[i].data->data,
2971 info[i].data->length);
2974 done:
2975 if (is_valid_policy_hnd(&hnd)) {
2976 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2979 return result;
2982 /****************************************************************************
2983 ****************************************************************************/
2985 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2986 TALLOC_CTX *mem_ctx, int argc,
2987 const char **argv)
2989 WERROR result;
2990 const char *printername;
2991 const char *keyname = NULL;
2992 struct policy_handle hnd;
2993 const char **key_buffer = NULL;
2994 int i;
2995 uint32_t offered = 0;
2997 if (argc < 2 || argc > 4) {
2998 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
2999 return WERR_OK;
3002 if (argc >= 3) {
3003 keyname = argv[2];
3004 } else {
3005 keyname = "";
3008 if (argc == 4) {
3009 offered = atoi(argv[3]);
3012 /* Open printer handle */
3014 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3016 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3017 printername,
3018 SEC_FLAG_MAXIMUM_ALLOWED,
3019 &hnd);
3020 if (!W_ERROR_IS_OK(result)) {
3021 goto done;
3024 /* Enumerate subkeys */
3026 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3027 &hnd,
3028 keyname,
3029 &key_buffer,
3030 offered);
3032 if (!W_ERROR_IS_OK(result)) {
3033 goto done;
3036 for (i=0; key_buffer && key_buffer[i]; i++) {
3037 printf("%s\n", key_buffer[i]);
3040 done:
3042 if (is_valid_policy_hnd(&hnd)) {
3043 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3046 return result;
3049 /****************************************************************************
3050 ****************************************************************************/
3052 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3053 TALLOC_CTX *mem_ctx, int argc,
3054 const char **argv)
3056 const char *printername;
3057 const char *clientname;
3058 struct policy_handle hnd;
3059 WERROR result;
3060 NTSTATUS status;
3061 struct spoolss_NotifyOption option;
3063 if (argc != 2) {
3064 printf("Usage: %s printername\n", argv[0]);
3065 result = WERR_OK;
3066 goto done;
3069 /* Open printer */
3071 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3073 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3074 printername,
3075 SEC_FLAG_MAXIMUM_ALLOWED,
3076 &hnd);
3077 if (!W_ERROR_IS_OK(result)) {
3078 printf("Error opening %s\n", argv[1]);
3079 goto done;
3082 /* Create spool options */
3084 option.version = 2;
3085 option.count = 2;
3087 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3088 if (option.types == NULL) {
3089 result = WERR_NOMEM;
3090 goto done;
3093 option.types[0].type = PRINTER_NOTIFY_TYPE;
3094 option.types[0].count = 1;
3095 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3096 if (option.types[0].fields == NULL) {
3097 result = WERR_NOMEM;
3098 goto done;
3100 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3102 option.types[1].type = JOB_NOTIFY_TYPE;
3103 option.types[1].count = 1;
3104 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3105 if (option.types[1].fields == NULL) {
3106 result = WERR_NOMEM;
3107 goto done;
3109 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3111 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3112 if (!clientname) {
3113 result = WERR_NOMEM;
3114 goto done;
3117 /* Send rffpcnex */
3119 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3120 &hnd,
3123 clientname,
3124 123,
3125 &option,
3126 &result);
3127 if (!W_ERROR_IS_OK(result)) {
3128 printf("Error rffpcnex %s\n", argv[1]);
3129 goto done;
3132 done:
3133 if (is_valid_policy_hnd(&hnd))
3134 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3136 return result;
3139 /****************************************************************************
3140 ****************************************************************************/
3142 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3143 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3145 union spoolss_PrinterInfo info1, info2;
3146 WERROR werror;
3147 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3149 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3150 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3151 hnd1,
3154 &info1);
3155 if ( !W_ERROR_IS_OK(werror) ) {
3156 printf("failed (%s)\n", win_errstr(werror));
3157 talloc_destroy(mem_ctx);
3158 return false;
3160 printf("ok\n");
3162 printf("Retrieving printer properties for %s...", cli2->desthost);
3163 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3164 hnd2,
3167 &info2);
3168 if ( !W_ERROR_IS_OK(werror) ) {
3169 printf("failed (%s)\n", win_errstr(werror));
3170 talloc_destroy(mem_ctx);
3171 return false;
3173 printf("ok\n");
3175 talloc_destroy(mem_ctx);
3177 return true;
3180 /****************************************************************************
3181 ****************************************************************************/
3183 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3184 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3186 union spoolss_PrinterInfo info1, info2;
3187 WERROR werror;
3188 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3189 struct security_descriptor *sd1, *sd2;
3190 bool result = true;
3193 printf("Retrieving printer security for %s...", cli1->desthost);
3194 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3195 hnd1,
3198 &info1);
3199 if ( !W_ERROR_IS_OK(werror) ) {
3200 printf("failed (%s)\n", win_errstr(werror));
3201 result = false;
3202 goto done;
3204 printf("ok\n");
3206 printf("Retrieving printer security for %s...", cli2->desthost);
3207 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3208 hnd2,
3211 &info2);
3212 if ( !W_ERROR_IS_OK(werror) ) {
3213 printf("failed (%s)\n", win_errstr(werror));
3214 result = false;
3215 goto done;
3217 printf("ok\n");
3220 printf("++ ");
3222 sd1 = info1.info3.secdesc;
3223 sd2 = info2.info3.secdesc;
3225 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3226 printf("NULL secdesc!\n");
3227 result = false;
3228 goto done;
3231 if (!security_descriptor_equal( sd1, sd2 ) ) {
3232 printf("Security Descriptors *not* equal!\n");
3233 result = false;
3234 goto done;
3237 printf("Security descriptors match\n");
3239 done:
3240 talloc_destroy(mem_ctx);
3241 return result;
3245 /****************************************************************************
3246 ****************************************************************************/
3248 extern struct user_auth_info *rpcclient_auth_info;
3250 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3251 TALLOC_CTX *mem_ctx, int argc,
3252 const char **argv)
3254 const char *printername;
3255 char *printername_path = NULL;
3256 struct cli_state *cli_server2 = NULL;
3257 struct rpc_pipe_client *cli2 = NULL;
3258 struct policy_handle hPrinter1, hPrinter2;
3259 NTSTATUS nt_status;
3260 WERROR werror;
3262 if ( argc != 3 ) {
3263 printf("Usage: %s <printer> <server>\n", argv[0]);
3264 return WERR_OK;
3267 printername = argv[1];
3269 /* first get the connection to the remote server */
3271 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3272 NULL, 0,
3273 "IPC$", "IPC",
3274 get_cmdline_auth_info_username(rpcclient_auth_info),
3275 lp_workgroup(),
3276 get_cmdline_auth_info_password(rpcclient_auth_info),
3277 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3278 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3280 if ( !NT_STATUS_IS_OK(nt_status) )
3281 return WERR_GENERAL_FAILURE;
3283 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3284 &cli2);
3285 if (!NT_STATUS_IS_OK(nt_status)) {
3286 printf("failed to open spoolss pipe on server %s (%s)\n",
3287 argv[2], nt_errstr(nt_status));
3288 return WERR_GENERAL_FAILURE;
3291 /* now open up both printers */
3293 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3295 printf("Opening %s...", printername_path);
3297 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3298 printername_path,
3299 PRINTER_ALL_ACCESS,
3300 &hPrinter1);
3301 if ( !W_ERROR_IS_OK(werror) ) {
3302 printf("failed (%s)\n", win_errstr(werror));
3303 goto done;
3305 printf("ok\n");
3307 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3309 printf("Opening %s...", printername_path);
3310 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3311 printername_path,
3312 PRINTER_ALL_ACCESS,
3313 &hPrinter2);
3314 if ( !W_ERROR_IS_OK(werror) ) {
3315 printf("failed (%s)\n", win_errstr(werror));
3316 goto done;
3318 printf("ok\n");
3320 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3321 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3322 #if 0
3323 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3324 #endif
3327 done:
3328 /* cleanup */
3330 printf("Closing printers...");
3331 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3332 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3333 printf("ok\n");
3335 /* close the second remote connection */
3337 cli_shutdown( cli_server2 );
3338 return WERR_OK;
3341 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3343 printf("print_processor_name: %s\n", r->print_processor_name);
3346 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3347 TALLOC_CTX *mem_ctx, int argc,
3348 const char **argv)
3350 WERROR werror;
3351 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3352 uint32_t num_procs, level = 1, i;
3353 union spoolss_PrintProcessorInfo *procs;
3355 /* Parse the command arguments */
3357 if (argc < 1 || argc > 4) {
3358 printf ("Usage: %s [environment] [level]\n", argv[0]);
3359 return WERR_OK;
3362 if (argc >= 2) {
3363 environment = argv[1];
3366 if (argc == 3) {
3367 level = atoi(argv[2]);
3370 /* Enumerate Print Processors */
3372 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3373 cli->srv_name_slash,
3374 environment,
3375 level,
3377 &num_procs,
3378 &procs);
3379 if (!W_ERROR_IS_OK(werror))
3380 goto done;
3382 /* Display output */
3384 for (i = 0; i < num_procs; i++) {
3385 switch (level) {
3386 case 1:
3387 display_proc_info1(&procs[i].info1);
3388 break;
3392 done:
3393 return werror;
3396 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3398 printf("name_array: %s\n", r->name_array);
3401 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3402 TALLOC_CTX *mem_ctx, int argc,
3403 const char **argv)
3405 WERROR werror;
3406 const char *print_processor_name = "winprint";
3407 uint32_t num_procs, level = 1, i;
3408 union spoolss_PrintProcDataTypesInfo *procs;
3410 /* Parse the command arguments */
3412 if (argc < 1 || argc > 4) {
3413 printf ("Usage: %s [environment] [level]\n", argv[0]);
3414 return WERR_OK;
3417 if (argc >= 2) {
3418 print_processor_name = argv[1];
3421 if (argc == 3) {
3422 level = atoi(argv[2]);
3425 /* Enumerate Print Processor Data Types */
3427 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3428 cli->srv_name_slash,
3429 print_processor_name,
3430 level,
3432 &num_procs,
3433 &procs);
3434 if (!W_ERROR_IS_OK(werror))
3435 goto done;
3437 /* Display output */
3439 for (i = 0; i < num_procs; i++) {
3440 switch (level) {
3441 case 1:
3442 display_proc_data_types_info1(&procs[i].info1);
3443 break;
3447 done:
3448 return werror;
3451 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3453 printf("monitor_name: %s\n", r->monitor_name);
3456 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3458 printf("monitor_name: %s\n", r->monitor_name);
3459 printf("environment: %s\n", r->environment);
3460 printf("dll_name: %s\n", r->dll_name);
3463 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3464 TALLOC_CTX *mem_ctx, int argc,
3465 const char **argv)
3467 WERROR werror;
3468 uint32_t count, level = 1, i;
3469 union spoolss_MonitorInfo *info;
3471 /* Parse the command arguments */
3473 if (argc > 2) {
3474 printf("Usage: %s [level]\n", argv[0]);
3475 return WERR_OK;
3478 if (argc == 2) {
3479 level = atoi(argv[1]);
3482 /* Enumerate Print Monitors */
3484 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3485 cli->srv_name_slash,
3486 level,
3488 &count,
3489 &info);
3490 if (!W_ERROR_IS_OK(werror)) {
3491 goto done;
3494 /* Display output */
3496 for (i = 0; i < count; i++) {
3497 switch (level) {
3498 case 1:
3499 display_monitor1(&info[i].info1);
3500 break;
3501 case 2:
3502 display_monitor2(&info[i].info2);
3503 break;
3507 done:
3508 return werror;
3511 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3512 TALLOC_CTX *mem_ctx, int argc,
3513 const char **argv)
3515 WERROR result;
3516 NTSTATUS status;
3517 struct policy_handle handle, gdi_handle;
3518 const char *printername;
3519 struct spoolss_DevmodeContainer devmode_ctr;
3521 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3523 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3524 printername,
3525 SEC_FLAG_MAXIMUM_ALLOWED,
3526 &handle);
3527 if (!W_ERROR_IS_OK(result)) {
3528 return result;
3531 ZERO_STRUCT(devmode_ctr);
3533 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3534 &handle,
3535 &gdi_handle,
3536 &devmode_ctr,
3537 &result);
3538 if (!W_ERROR_IS_OK(result)) {
3539 goto done;
3542 done:
3543 if (is_valid_policy_hnd(&gdi_handle)) {
3544 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3546 if (is_valid_policy_hnd(&handle)) {
3547 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3550 return result;
3553 /* List of commands exported by this module */
3554 struct cmd_set spoolss_commands[] = {
3556 { "SPOOLSS" },
3558 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3559 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3560 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3561 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3562 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3563 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3564 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3565 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3566 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3567 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3568 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3569 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3570 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3571 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3572 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3573 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3574 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3575 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3576 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3577 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3578 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3579 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3580 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3581 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3582 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3583 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3584 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3585 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3586 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3587 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3588 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3589 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3590 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3591 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3592 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3594 { NULL }