s3-waf: Add check for dirent.d_off member
[Samba/gebeck_regimport.git] / source3 / rpcclient / cmd_spoolss.c
blobf4646c43c3c05a118cf944f00b6f2ad1c61d7311
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/cli_spoolss.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
30 #include "registry.h"
31 #include "registry/reg_objects.h"
33 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
34 { \
35 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
36 _cli->srv_name_slash, _arg); \
37 W_ERROR_HAVE_NO_MEMORY(_printername); \
40 /* The version int is used by getdrivers. Note that
41 all architecture strings that support mutliple
42 versions must be grouped together since enumdrivers
43 uses this property to prevent issuing multiple
44 enumdriver calls for the same arch */
47 static const struct print_architecture_table_node archi_table[]= {
49 {"Windows 4.0", "WIN40", 0 },
50 {"Windows NT x86", "W32X86", 2 },
51 {"Windows NT x86", "W32X86", 3 },
52 {"Windows NT R4000", "W32MIPS", 2 },
53 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
54 {"Windows NT PowerPC", "W32PPC", 2 },
55 {"Windows IA64", "IA64", 3 },
56 {"Windows x64", "x64", 3 },
57 {NULL, "", -1 }
60 /**
61 * @file
63 * rpcclient module for SPOOLSS rpc pipe.
65 * This generally just parses and checks command lines, and then calls
66 * a cli_spoolss function.
67 **/
69 /****************************************************************************
70 function to do the mapping between the long architecture name and
71 the short one.
72 ****************************************************************************/
74 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
76 int i=-1;
78 DEBUG(107,("Getting architecture dependant directory\n"));
79 do {
80 i++;
81 } while ( (archi_table[i].long_archi!=NULL ) &&
82 StrCaseCmp(long_archi, archi_table[i].long_archi) );
84 if (archi_table[i].long_archi==NULL) {
85 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
86 return NULL;
89 /* this might be client code - but shouldn't this be an fstrcpy etc? */
92 DEBUGADD(108,("index: [%d]\n", i));
93 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
94 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
96 return archi_table[i].short_archi;
99 /****************************************************************************
100 ****************************************************************************/
102 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
103 TALLOC_CTX *mem_ctx,
104 int argc, const char **argv)
106 WERROR werror;
107 struct policy_handle hnd;
109 if (argc != 2) {
110 printf("Usage: %s <printername>\n", argv[0]);
111 return WERR_OK;
114 if (!cli)
115 return WERR_GENERAL_FAILURE;
117 /* Open the printer handle */
119 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
120 argv[1],
121 PRINTER_ALL_ACCESS,
122 &hnd);
123 if (W_ERROR_IS_OK(werror)) {
124 printf("Printer %s opened successfully\n", argv[1]);
125 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
127 if (!W_ERROR_IS_OK(werror)) {
128 printf("Error closing printer handle! (%s)\n",
129 get_dos_error_msg(werror));
133 return werror;
137 /****************************************************************************
138 ****************************************************************************/
140 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
142 if (!r)
143 return;
145 printf("\tprintername:[%s]\n", r->printername);
146 printf("\tservername:[%s]\n", r->servername);
147 printf("\tcjobs:[0x%x]\n", r->cjobs);
148 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
149 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
150 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
151 r->time.day, r->time.day_of_week);
152 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
153 r->time.second, r->time.millisecond);
155 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
156 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
158 printf("\tversion:[0x%x]\n", r->version);
159 printf("\tfree_build:[0x%x]\n", r->free_build);
160 printf("\tspooling:[0x%x]\n", r->spooling);
161 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
162 printf("\tsession_counter:[0x%x]\n", r->session_counter);
163 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
164 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
165 printf("\tjob_error:[0x%x]\n", r->job_error);
166 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
167 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
168 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
169 printf("\tchange_id:[0x%x]\n", r->change_id);
170 printf("\tlast_error: %s\n", win_errstr(r->last_error));
171 printf("\tstatus:[0x%x]\n", r->status);
172 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
173 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
174 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
175 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
176 printf("\tref_ic:[0x%x]\n", r->ref_ic);
177 printf("\treserved2:[0x%x]\n", r->reserved2);
178 printf("\treserved3:[0x%x]\n", r->reserved3);
180 printf("\n");
183 /****************************************************************************
184 ****************************************************************************/
186 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
188 printf("\tflags:[0x%x]\n", r->flags);
189 printf("\tname:[%s]\n", r->name);
190 printf("\tdescription:[%s]\n", r->description);
191 printf("\tcomment:[%s]\n", r->comment);
193 printf("\n");
196 /****************************************************************************
197 ****************************************************************************/
199 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
201 printf("\tservername:[%s]\n", r->servername);
202 printf("\tprintername:[%s]\n", r->printername);
203 printf("\tsharename:[%s]\n", r->sharename);
204 printf("\tportname:[%s]\n", r->portname);
205 printf("\tdrivername:[%s]\n", r->drivername);
206 printf("\tcomment:[%s]\n", r->comment);
207 printf("\tlocation:[%s]\n", r->location);
208 printf("\tsepfile:[%s]\n", r->sepfile);
209 printf("\tprintprocessor:[%s]\n", r->printprocessor);
210 printf("\tdatatype:[%s]\n", r->datatype);
211 printf("\tparameters:[%s]\n", r->parameters);
212 printf("\tattributes:[0x%x]\n", r->attributes);
213 printf("\tpriority:[0x%x]\n", r->priority);
214 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
215 printf("\tstarttime:[0x%x]\n", r->starttime);
216 printf("\tuntiltime:[0x%x]\n", r->untiltime);
217 printf("\tstatus:[0x%x]\n", r->status);
218 printf("\tcjobs:[0x%x]\n", r->cjobs);
219 printf("\taverageppm:[0x%x]\n", r->averageppm);
221 if (r->secdesc)
222 display_sec_desc(r->secdesc);
224 printf("\n");
227 /****************************************************************************
228 ****************************************************************************/
230 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
232 display_sec_desc(r->secdesc);
234 printf("\n");
237 /****************************************************************************
238 ****************************************************************************/
240 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
242 printf("\tservername:[%s]\n", r->servername);
243 printf("\tprintername:[%s]\n", r->printername);
244 printf("\tattributes:[0x%x]\n", r->attributes);
245 printf("\n");
248 /****************************************************************************
249 ****************************************************************************/
251 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
253 printf("\tprintername:[%s]\n", r->printername);
254 printf("\tportname:[%s]\n", r->portname);
255 printf("\tattributes:[0x%x]\n", r->attributes);
256 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
257 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
258 printf("\n");
261 /****************************************************************************
262 ****************************************************************************/
264 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
266 printf("\tstatus:[0x%x]\n", r->status);
267 printf("\n");
270 /****************************************************************************
271 ****************************************************************************/
273 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
275 printf("\tguid:[%s]\n", r->guid);
276 printf("\taction:[0x%x]\n", r->action);
277 printf("\n");
280 /****************************************************************************
281 ****************************************************************************/
283 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
284 TALLOC_CTX *mem_ctx,
285 int argc, const char **argv)
287 WERROR result;
288 uint32_t level = 1;
289 union spoolss_PrinterInfo *info;
290 uint32_t i, count;
291 const char *name;
292 uint32_t flags = PRINTER_ENUM_LOCAL;
294 if (argc > 4) {
295 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
296 return WERR_OK;
299 if (argc >= 2) {
300 level = atoi(argv[1]);
303 if (argc >= 3) {
304 name = argv[2];
305 } else {
306 name = cli->srv_name_slash;
309 if (argc == 4) {
310 flags = atoi(argv[3]);
313 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
314 flags,
315 name,
316 level,
318 &count,
319 &info);
320 if (W_ERROR_IS_OK(result)) {
322 if (!count) {
323 printf ("No printers returned.\n");
324 goto done;
327 for (i = 0; i < count; i++) {
328 switch (level) {
329 case 0:
330 display_print_info0(&info[i].info0);
331 break;
332 case 1:
333 display_print_info1(&info[i].info1);
334 break;
335 case 2:
336 display_print_info2(&info[i].info2);
337 break;
338 case 3:
339 display_print_info3(&info[i].info3);
340 break;
341 case 4:
342 display_print_info4(&info[i].info4);
343 break;
344 case 5:
345 display_print_info5(&info[i].info5);
346 break;
347 case 6:
348 display_print_info6(&info[i].info6);
349 break;
350 default:
351 printf("unknown info level %d\n", level);
352 goto done;
356 done:
358 return result;
361 /****************************************************************************
362 ****************************************************************************/
364 static void display_port_info_1(struct spoolss_PortInfo1 *r)
366 printf("\tPort Name:\t[%s]\n", r->port_name);
369 /****************************************************************************
370 ****************************************************************************/
372 static void display_port_info_2(struct spoolss_PortInfo2 *r)
374 printf("\tPort Name:\t[%s]\n", r->port_name);
375 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
376 printf("\tDescription:\t[%s]\n", r->description);
377 printf("\tPort Type:\t" );
378 if (r->port_type) {
379 int comma = 0; /* hack */
380 printf( "[" );
381 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
382 printf( "Read" );
383 comma = 1;
385 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
386 printf( "%sWrite", comma ? ", " : "" );
387 comma = 1;
389 /* These two have slightly different interpretations
390 on 95/98/ME but I'm disregarding that for now */
391 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
392 printf( "%sRedirected", comma ? ", " : "" );
393 comma = 1;
395 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
396 printf( "%sNet-Attached", comma ? ", " : "" );
398 printf( "]\n" );
399 } else {
400 printf( "[Unset]\n" );
402 printf("\tReserved:\t[%d]\n", r->reserved);
403 printf("\n");
406 /****************************************************************************
407 ****************************************************************************/
409 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
410 TALLOC_CTX *mem_ctx, int argc,
411 const char **argv)
413 WERROR result;
414 uint32_t level = 1;
415 uint32_t count;
416 union spoolss_PortInfo *info;
418 if (argc > 2) {
419 printf("Usage: %s [level]\n", argv[0]);
420 return WERR_OK;
423 if (argc == 2) {
424 level = atoi(argv[1]);
427 /* Enumerate ports */
429 result = rpccli_spoolss_enumports(cli, mem_ctx,
430 cli->srv_name_slash,
431 level,
433 &count,
434 &info);
435 if (W_ERROR_IS_OK(result)) {
436 int i;
438 for (i = 0; i < count; i++) {
439 switch (level) {
440 case 1:
441 display_port_info_1(&info[i].info1);
442 break;
443 case 2:
444 display_port_info_2(&info[i].info2);
445 break;
446 default:
447 printf("unknown info level %d\n", level);
448 break;
453 return result;
456 /****************************************************************************
457 ****************************************************************************/
459 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
460 TALLOC_CTX *mem_ctx,
461 int argc, const char **argv)
463 struct policy_handle pol;
464 WERROR result;
465 NTSTATUS status;
466 uint32_t info_level = 2;
467 union spoolss_PrinterInfo info;
468 struct spoolss_SetPrinterInfoCtr info_ctr;
469 struct spoolss_SetPrinterInfo2 info2;
470 const char *printername, *comment = NULL;
471 struct spoolss_DevmodeContainer devmode_ctr;
472 struct sec_desc_buf secdesc_ctr;
474 if (argc == 1 || argc > 3) {
475 printf("Usage: %s printername comment\n", argv[0]);
477 return WERR_OK;
480 /* Open a printer handle */
481 if (argc == 3) {
482 comment = argv[2];
485 ZERO_STRUCT(devmode_ctr);
486 ZERO_STRUCT(secdesc_ctr);
488 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
490 /* get a printer handle */
491 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
492 printername,
493 PRINTER_ALL_ACCESS,
494 &pol);
495 if (!W_ERROR_IS_OK(result))
496 goto done;
498 /* Get printer info */
499 result = rpccli_spoolss_getprinter(cli, mem_ctx,
500 &pol,
501 info_level,
503 &info);
504 if (!W_ERROR_IS_OK(result))
505 goto done;
508 /* Modify the comment. */
509 info2.servername = info.info2.servername;
510 info2.printername = info.info2.printername;
511 info2.sharename = info.info2.sharename;
512 info2.portname = info.info2.portname;
513 info2.drivername = info.info2.drivername;
514 info2.comment = comment;
515 info2.location = info.info2.location;
516 info2.devmode_ptr = 0;
517 info2.sepfile = info.info2.sepfile;
518 info2.printprocessor = info.info2.printprocessor;
519 info2.datatype = info.info2.datatype;
520 info2.parameters = info.info2.parameters;
521 info2.secdesc_ptr = 0;
522 info2.attributes = info.info2.attributes;
523 info2.priority = info.info2.priority;
524 info2.defaultpriority = info.info2.defaultpriority;
525 info2.starttime = info.info2.starttime;
526 info2.untiltime = info.info2.untiltime;
527 info2.status = info.info2.status;
528 info2.cjobs = info.info2.cjobs;
529 info2.averageppm = info.info2.averageppm;
531 info_ctr.level = 2;
532 info_ctr.info.info2 = &info2;
534 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
535 &pol,
536 &info_ctr,
537 &devmode_ctr,
538 &secdesc_ctr,
539 0, /* command */
540 &result);
541 if (W_ERROR_IS_OK(result))
542 printf("Success in setting comment.\n");
544 done:
545 if (is_valid_policy_hnd(&pol))
546 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
548 return result;
551 /****************************************************************************
552 ****************************************************************************/
554 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
555 TALLOC_CTX *mem_ctx,
556 int argc, const char **argv)
558 struct policy_handle pol;
559 WERROR result;
560 NTSTATUS status;
561 uint32_t info_level = 2;
562 union spoolss_PrinterInfo info;
563 const char *printername,
564 *new_printername = NULL;
565 struct spoolss_SetPrinterInfoCtr info_ctr;
566 struct spoolss_SetPrinterInfo2 info2;
567 struct spoolss_DevmodeContainer devmode_ctr;
568 struct sec_desc_buf secdesc_ctr;
570 ZERO_STRUCT(devmode_ctr);
571 ZERO_STRUCT(secdesc_ctr);
573 if (argc == 1 || argc > 3) {
574 printf("Usage: %s printername new_printername\n", argv[0]);
576 return WERR_OK;
579 /* Open a printer handle */
580 if (argc == 3) {
581 new_printername = argv[2];
584 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
586 /* get a printer handle */
587 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
588 printername,
589 PRINTER_ALL_ACCESS,
590 &pol);
591 if (!W_ERROR_IS_OK(result))
592 goto done;
594 /* Get printer info */
595 result = rpccli_spoolss_getprinter(cli, mem_ctx,
596 &pol,
597 info_level,
599 &info);
600 if (!W_ERROR_IS_OK(result))
601 goto done;
603 /* Modify the printername. */
604 info2.servername = info.info2.servername;
605 info2.printername = new_printername;
606 info2.sharename = info.info2.sharename;
607 info2.portname = info.info2.portname;
608 info2.drivername = info.info2.drivername;
609 info2.comment = info.info2.comment;
610 info2.location = info.info2.location;
611 info2.devmode_ptr = 0;
612 info2.sepfile = info.info2.sepfile;
613 info2.printprocessor = info.info2.printprocessor;
614 info2.datatype = info.info2.datatype;
615 info2.parameters = info.info2.parameters;
616 info2.secdesc_ptr = 0;
617 info2.attributes = info.info2.attributes;
618 info2.priority = info.info2.priority;
619 info2.defaultpriority = info.info2.defaultpriority;
620 info2.starttime = info.info2.starttime;
621 info2.untiltime = info.info2.untiltime;
622 info2.status = info.info2.status;
623 info2.cjobs = info.info2.cjobs;
624 info2.averageppm = info.info2.averageppm;
626 info_ctr.level = 2;
627 info_ctr.info.info2 = &info2;
629 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
630 &pol,
631 &info_ctr,
632 &devmode_ctr,
633 &secdesc_ctr,
634 0, /* command */
635 &result);
636 if (W_ERROR_IS_OK(result))
637 printf("Success in setting printername.\n");
639 done:
640 if (is_valid_policy_hnd(&pol))
641 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
643 return result;
646 /****************************************************************************
647 ****************************************************************************/
649 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
650 TALLOC_CTX *mem_ctx,
651 int argc, const char **argv)
653 struct policy_handle pol;
654 WERROR result;
655 uint32_t level = 1;
656 const char *printername;
657 union spoolss_PrinterInfo info;
659 if (argc == 1 || argc > 3) {
660 printf("Usage: %s <printername> [level]\n", argv[0]);
661 return WERR_OK;
664 /* Open a printer handle */
665 if (argc == 3) {
666 level = atoi(argv[2]);
669 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
671 /* get a printer handle */
673 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
674 printername,
675 SEC_FLAG_MAXIMUM_ALLOWED,
676 &pol);
677 if (!W_ERROR_IS_OK(result)) {
678 goto done;
681 /* Get printer info */
683 result = rpccli_spoolss_getprinter(cli, mem_ctx,
684 &pol,
685 level,
687 &info);
688 if (!W_ERROR_IS_OK(result)) {
689 goto done;
692 /* Display printer info */
693 switch (level) {
694 case 0:
695 display_print_info0(&info.info0);
696 break;
697 case 1:
698 display_print_info1(&info.info1);
699 break;
700 case 2:
701 display_print_info2(&info.info2);
702 break;
703 case 3:
704 display_print_info3(&info.info3);
705 break;
706 case 4:
707 display_print_info4(&info.info4);
708 break;
709 case 5:
710 display_print_info5(&info.info5);
711 break;
712 case 6:
713 display_print_info6(&info.info6);
714 break;
715 case 7:
716 display_print_info7(&info.info7);
717 break;
718 default:
719 printf("unknown info level %d\n", level);
720 break;
722 done:
723 if (is_valid_policy_hnd(&pol)) {
724 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
727 return result;
730 /****************************************************************************
731 ****************************************************************************/
733 static void display_reg_value(struct regval_blob *value)
735 const char *text = NULL;
736 DATA_BLOB blob;
738 switch(regval_type(value)) {
739 case REG_DWORD:
740 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
741 *((uint32_t *) regval_data_p(value)));
742 break;
743 case REG_SZ:
744 blob = data_blob_const(regval_data_p(value), regval_size(value));
745 pull_reg_sz(talloc_tos(), &blob, &text);
746 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
747 break;
748 case REG_BINARY: {
749 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
750 size_t i, len;
751 printf("%s: REG_BINARY:", regval_name(value));
752 len = strlen(hex);
753 for (i=0; i<len; i++) {
754 if (hex[i] == '\0') {
755 break;
757 if (i%40 == 0) {
758 putchar('\n');
760 putchar(hex[i]);
762 TALLOC_FREE(hex);
763 putchar('\n');
764 break;
766 case REG_MULTI_SZ: {
767 uint32_t i;
768 const char **values;
769 blob = data_blob_const(regval_data_p(value), regval_size(value));
771 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
772 d_printf("pull_reg_multi_sz failed\n");
773 break;
776 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
777 for (i=0; values[i] != NULL; i++) {
778 d_printf("%s\n", values[i]);
780 TALLOC_FREE(values);
781 break;
783 default:
784 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
789 /****************************************************************************
790 ****************************************************************************/
792 static void display_printer_data(const char *v,
793 enum winreg_Type type,
794 uint8_t *data,
795 uint32_t length)
797 int i;
798 union spoolss_PrinterData r;
799 DATA_BLOB blob = data_blob_const(data, length);
800 WERROR result;
802 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
803 if (!W_ERROR_IS_OK(result)) {
804 return;
807 switch (type) {
808 case REG_DWORD:
809 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
810 break;
811 case REG_SZ:
812 printf("%s: REG_SZ: %s\n", v, r.string);
813 break;
814 case REG_BINARY: {
815 char *hex = hex_encode_talloc(NULL,
816 r.binary.data, r.binary.length);
817 size_t len;
818 printf("%s: REG_BINARY:", v);
819 len = strlen(hex);
820 for (i=0; i<len; i++) {
821 if (hex[i] == '\0') {
822 break;
824 if (i%40 == 0) {
825 putchar('\n');
827 putchar(hex[i]);
829 TALLOC_FREE(hex);
830 putchar('\n');
831 break;
833 case REG_MULTI_SZ:
834 printf("%s: REG_MULTI_SZ: ", v);
835 for (i=0; r.string_array[i] != NULL; i++) {
836 printf("%s ", r.string_array[i]);
838 printf("\n");
839 break;
840 default:
841 printf("%s: unknown type 0x%02x:\n", v, type);
842 break;
846 /****************************************************************************
847 ****************************************************************************/
849 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
850 TALLOC_CTX *mem_ctx,
851 int argc, const char **argv)
853 struct policy_handle pol;
854 WERROR result;
855 fstring printername;
856 const char *valuename;
857 enum winreg_Type type;
858 uint8_t *data;
859 uint32_t needed;
861 if (argc != 3) {
862 printf("Usage: %s <printername> <valuename>\n", argv[0]);
863 printf("<printername> of . queries print server\n");
864 return WERR_OK;
866 valuename = argv[2];
868 /* Open a printer handle */
870 if (strncmp(argv[1], ".", sizeof(".")) == 0)
871 fstrcpy(printername, cli->srv_name_slash);
872 else
873 slprintf(printername, sizeof(printername)-1, "%s\\%s",
874 cli->srv_name_slash, argv[1]);
876 /* get a printer handle */
878 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
879 printername,
880 SEC_FLAG_MAXIMUM_ALLOWED,
881 &pol);
882 if (!W_ERROR_IS_OK(result))
883 goto done;
885 /* Get printer info */
887 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
888 &pol,
889 valuename,
891 &type,
892 &needed,
893 &data);
894 if (!W_ERROR_IS_OK(result))
895 goto done;
897 /* Display printer data */
899 display_printer_data(valuename, type, data, needed);
901 done:
902 if (is_valid_policy_hnd(&pol))
903 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
905 return result;
908 /****************************************************************************
909 ****************************************************************************/
911 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
912 TALLOC_CTX *mem_ctx,
913 int argc, const char **argv)
915 struct policy_handle pol;
916 WERROR result;
917 NTSTATUS status;
918 fstring printername;
919 const char *valuename, *keyname;
921 enum winreg_Type type;
922 uint8_t *data = NULL;
923 uint32_t offered = 0;
924 uint32_t needed;
926 if (argc != 4) {
927 printf("Usage: %s <printername> <keyname> <valuename>\n",
928 argv[0]);
929 printf("<printername> of . queries print server\n");
930 return WERR_OK;
932 valuename = argv[3];
933 keyname = argv[2];
935 /* Open a printer handle */
937 if (strncmp(argv[1], ".", sizeof(".")) == 0)
938 fstrcpy(printername, cli->srv_name_slash);
939 else
940 slprintf(printername, sizeof(printername)-1, "%s\\%s",
941 cli->srv_name_slash, argv[1]);
943 /* get a printer handle */
945 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
946 printername,
947 SEC_FLAG_MAXIMUM_ALLOWED,
948 &pol);
949 if (!W_ERROR_IS_OK(result))
950 goto done;
952 /* Get printer info */
954 data = talloc_zero_array(mem_ctx, uint8_t, offered);
955 if (!data) {
956 goto done;
959 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
960 &pol,
961 keyname,
962 valuename,
963 &type,
964 data,
965 offered,
966 &needed,
967 &result);
968 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
969 offered = needed;
970 data = talloc_zero_array(mem_ctx, uint8_t, offered);
971 if (!data) {
972 goto done;
974 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
975 &pol,
976 keyname,
977 valuename,
978 &type,
979 data,
980 offered,
981 &needed,
982 &result);
985 if (!NT_STATUS_IS_OK(status)) {
986 goto done;
989 if (!W_ERROR_IS_OK(result))
990 goto done;
992 /* Display printer data */
994 display_printer_data(valuename, type, data, needed);
997 done:
998 if (is_valid_policy_hnd(&pol))
999 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1001 return result;
1004 /****************************************************************************
1005 ****************************************************************************/
1007 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1009 if (!r) {
1010 return;
1013 printf("Printer Driver Info 1:\n");
1014 printf("\tDriver Name: [%s]\n", r->driver_name);
1015 printf("\n");
1018 /****************************************************************************
1019 ****************************************************************************/
1021 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1023 if (!r) {
1024 return;
1027 printf("Printer Driver Info 2:\n");
1028 printf("\tVersion: [%x]\n", r->version);
1029 printf("\tDriver Name: [%s]\n", r->driver_name);
1030 printf("\tArchitecture: [%s]\n", r->architecture);
1031 printf("\tDriver Path: [%s]\n", r->driver_path);
1032 printf("\tDatafile: [%s]\n", r->data_file);
1033 printf("\tConfigfile: [%s]\n", r->config_file);
1034 printf("\n");
1037 /****************************************************************************
1038 ****************************************************************************/
1040 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1042 int i;
1044 if (!r) {
1045 return;
1048 printf("Printer Driver Info 3:\n");
1049 printf("\tVersion: [%x]\n", r->version);
1050 printf("\tDriver Name: [%s]\n", r->driver_name);
1051 printf("\tArchitecture: [%s]\n", r->architecture);
1052 printf("\tDriver Path: [%s]\n", r->driver_path);
1053 printf("\tDatafile: [%s]\n", r->data_file);
1054 printf("\tConfigfile: [%s]\n", r->config_file);
1055 printf("\tHelpfile: [%s]\n", r->help_file);
1057 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1058 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1061 printf("\tMonitorname: [%s]\n", r->monitor_name);
1062 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1063 printf("\n");
1066 /****************************************************************************
1067 ****************************************************************************/
1069 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1071 int i;
1073 if (!r) {
1074 return;
1077 printf("Printer Driver Info 4:\n");
1078 printf("\tVersion: [%x]\n", r->version);
1079 printf("\tDriver Name: [%s]\n", r->driver_name);
1080 printf("\tArchitecture: [%s]\n", r->architecture);
1081 printf("\tDriver Path: [%s]\n", r->driver_path);
1082 printf("\tDatafile: [%s]\n", r->data_file);
1083 printf("\tConfigfile: [%s]\n", r->config_file);
1084 printf("\tHelpfile: [%s]\n", r->help_file);
1086 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1087 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1090 printf("\tMonitorname: [%s]\n", r->monitor_name);
1091 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1093 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1094 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1096 printf("\n");
1099 /****************************************************************************
1100 ****************************************************************************/
1102 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1104 if (!r) {
1105 return;
1108 printf("Printer Driver Info 5:\n");
1109 printf("\tVersion: [%x]\n", r->version);
1110 printf("\tDriver Name: [%s]\n", r->driver_name);
1111 printf("\tArchitecture: [%s]\n", r->architecture);
1112 printf("\tDriver Path: [%s]\n", r->driver_path);
1113 printf("\tDatafile: [%s]\n", r->data_file);
1114 printf("\tConfigfile: [%s]\n", r->config_file);
1115 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1116 printf("\tConfig Version: [0x%x]\n", r->config_version);
1117 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1118 printf("\n");
1121 /****************************************************************************
1122 ****************************************************************************/
1124 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1126 int i;
1128 if (!r) {
1129 return;
1132 printf("Printer Driver Info 6:\n");
1133 printf("\tVersion: [%x]\n", r->version);
1134 printf("\tDriver Name: [%s]\n", r->driver_name);
1135 printf("\tArchitecture: [%s]\n", r->architecture);
1136 printf("\tDriver Path: [%s]\n", r->driver_path);
1137 printf("\tDatafile: [%s]\n", r->data_file);
1138 printf("\tConfigfile: [%s]\n", r->config_file);
1139 printf("\tHelpfile: [%s]\n", r->help_file);
1141 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1142 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1145 printf("\tMonitorname: [%s]\n", r->monitor_name);
1146 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1148 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1149 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1152 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1153 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1154 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1155 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1156 printf("\tHardware ID: [%s]\n", r->hardware_id);
1157 printf("\tProvider: [%s]\n", r->provider);
1159 printf("\n");
1162 /****************************************************************************
1163 ****************************************************************************/
1165 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1167 int i;
1169 if (!r) {
1170 return;
1173 printf("Printer Driver Info 8:\n");
1174 printf("\tVersion: [%x]\n", r->version);
1175 printf("\tDriver Name: [%s]\n", r->driver_name);
1176 printf("\tArchitecture: [%s]\n", r->architecture);
1177 printf("\tDriver Path: [%s]\n", r->driver_path);
1178 printf("\tDatafile: [%s]\n", r->data_file);
1179 printf("\tConfigfile: [%s]\n", r->config_file);
1180 printf("\tHelpfile: [%s]\n", r->help_file);
1181 printf("\tMonitorname: [%s]\n", r->monitor_name);
1182 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1184 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1185 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1188 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1189 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1192 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1193 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1194 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1195 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1196 printf("\tHardware ID: [%s]\n", r->hardware_id);
1197 printf("\tProvider: [%s]\n", r->provider);
1198 printf("\tPrint Processor: [%s]\n", r->print_processor);
1199 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1200 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1201 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1203 printf("\tInf Path: [%s]\n", r->inf_path);
1204 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1205 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1206 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1208 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1209 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1210 (long long unsigned int)r->min_inbox_driver_ver_version);
1212 printf("\n");
1215 /****************************************************************************
1216 ****************************************************************************/
1218 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1219 TALLOC_CTX *mem_ctx,
1220 int argc, const char **argv)
1222 struct policy_handle pol;
1223 WERROR werror;
1224 uint32_t level = 3;
1225 const char *printername;
1226 uint32_t i;
1227 bool success = false;
1228 union spoolss_DriverInfo info;
1229 uint32_t server_major_version;
1230 uint32_t server_minor_version;
1232 if ((argc == 1) || (argc > 3)) {
1233 printf("Usage: %s <printername> [level]\n", argv[0]);
1234 return WERR_OK;
1237 /* get the arguments need to open the printer handle */
1239 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1241 if (argc == 3) {
1242 level = atoi(argv[2]);
1245 /* Open a printer handle */
1247 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1248 printername,
1249 PRINTER_ACCESS_USE,
1250 &pol);
1251 if (!W_ERROR_IS_OK(werror)) {
1252 printf("Error opening printer handle for %s!\n", printername);
1253 return werror;
1256 /* loop through and print driver info level for each architecture */
1258 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1260 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1261 &pol,
1262 archi_table[i].long_archi,
1263 level,
1264 0, /* offered */
1265 archi_table[i].version,
1267 &info,
1268 &server_major_version,
1269 &server_minor_version);
1270 if (!W_ERROR_IS_OK(werror)) {
1271 continue;
1274 /* need at least one success */
1276 success = true;
1278 printf("\n[%s]\n", archi_table[i].long_archi);
1280 switch (level) {
1281 case 1:
1282 display_print_driver1(&info.info1);
1283 break;
1284 case 2:
1285 display_print_driver2(&info.info2);
1286 break;
1287 case 3:
1288 display_print_driver3(&info.info3);
1289 break;
1290 case 4:
1291 display_print_driver4(&info.info4);
1292 break;
1293 case 5:
1294 display_print_driver5(&info.info5);
1295 break;
1296 case 6:
1297 display_print_driver6(&info.info6);
1298 break;
1299 case 8:
1300 display_print_driver8(&info.info8);
1301 break;
1302 default:
1303 printf("unknown info level %d\n", level);
1304 break;
1308 /* Cleanup */
1310 if (is_valid_policy_hnd(&pol)) {
1311 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1314 if (success) {
1315 werror = WERR_OK;
1318 return werror;
1321 /****************************************************************************
1322 ****************************************************************************/
1324 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1325 TALLOC_CTX *mem_ctx,
1326 const char *architecture,
1327 uint32_t level)
1329 WERROR werror;
1330 uint32_t count = 0;
1331 union spoolss_DriverInfo *info = NULL;
1332 uint32_t j;
1334 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1335 cli->srv_name_slash,
1336 architecture,
1337 level,
1339 &count,
1340 &info);
1342 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1343 printf("Server does not support environment [%s]\n",
1344 architecture);
1345 return WERR_OK;
1348 if (count == 0) {
1349 return WERR_OK;
1352 if (!W_ERROR_IS_OK(werror)) {
1353 printf("Error getting driver for environment [%s] - %s\n",
1354 architecture, win_errstr(werror));
1355 return werror;
1358 printf("\n[%s]\n", architecture);
1360 switch (level) {
1361 case 1:
1362 for (j=0; j < count; j++) {
1363 display_print_driver1(&info[j].info1);
1365 break;
1366 case 2:
1367 for (j=0; j < count; j++) {
1368 display_print_driver2(&info[j].info2);
1370 break;
1371 case 3:
1372 for (j=0; j < count; j++) {
1373 display_print_driver3(&info[j].info3);
1375 break;
1376 case 4:
1377 for (j=0; j < count; j++) {
1378 display_print_driver4(&info[j].info4);
1380 break;
1381 case 5:
1382 for (j=0; j < count; j++) {
1383 display_print_driver5(&info[j].info5);
1385 break;
1386 case 6:
1387 for (j=0; j < count; j++) {
1388 display_print_driver6(&info[j].info6);
1390 break;
1391 case 8:
1392 for (j=0; j < count; j++) {
1393 display_print_driver8(&info[j].info8);
1395 break;
1396 default:
1397 printf("unknown info level %d\n", level);
1398 return WERR_UNKNOWN_LEVEL;
1401 return werror;
1404 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1405 TALLOC_CTX *mem_ctx,
1406 int argc, const char **argv)
1408 WERROR werror = WERR_OK;
1409 uint32_t level = 1;
1410 uint32_t i;
1411 const char *architecture = NULL;
1413 if (argc > 3) {
1414 printf("Usage: enumdrivers [level] [architecture]\n");
1415 return WERR_OK;
1418 if (argc >= 2) {
1419 level = atoi(argv[1]);
1422 if (argc == 3) {
1423 architecture = argv[2];
1426 if (architecture) {
1427 return enum_driver_by_architecture(cli, mem_ctx,
1428 architecture,
1429 level);
1432 /* loop through and print driver info level for each architecture */
1433 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1434 /* check to see if we already asked for this architecture string */
1436 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1437 continue;
1440 werror = enum_driver_by_architecture(cli, mem_ctx,
1441 archi_table[i].long_archi,
1442 level);
1443 if (!W_ERROR_IS_OK(werror)) {
1444 break;
1448 return werror;
1451 /****************************************************************************
1452 ****************************************************************************/
1454 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1456 printf("\tDirectory Name:[%s]\n", r->directory_name);
1459 /****************************************************************************
1460 ****************************************************************************/
1462 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1463 TALLOC_CTX *mem_ctx,
1464 int argc, const char **argv)
1466 WERROR result;
1467 NTSTATUS status;
1468 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1469 DATA_BLOB buffer;
1470 uint32_t offered;
1471 union spoolss_DriverDirectoryInfo info;
1472 uint32_t needed;
1474 if (argc > 2) {
1475 printf("Usage: %s [environment]\n", argv[0]);
1476 return WERR_OK;
1479 /* Get the arguments need to open the printer handle */
1481 if (argc == 2) {
1482 env = argv[1];
1485 /* Get the directory. Only use Info level 1 */
1487 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1488 cli->srv_name_slash,
1489 env,
1491 NULL, /* buffer */
1492 0, /* offered */
1493 NULL, /* info */
1494 &needed,
1495 &result);
1496 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1497 offered = needed;
1498 buffer = data_blob_talloc_zero(mem_ctx, needed);
1500 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1501 cli->srv_name_slash,
1502 env,
1504 &buffer,
1505 offered,
1506 &info,
1507 &needed,
1508 &result);
1511 if (W_ERROR_IS_OK(result)) {
1512 display_printdriverdir_1(&info.info1);
1515 return result;
1518 /****************************************************************************
1519 ****************************************************************************/
1521 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1522 struct spoolss_AddDriverInfo3 *info,
1523 const char *arch)
1526 int i;
1528 for (i=0; archi_table[i].long_archi != NULL; i++)
1530 if (strcmp(arch, archi_table[i].short_archi) == 0)
1532 info->version = archi_table[i].version;
1533 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1534 break;
1538 if (archi_table[i].long_archi == NULL)
1540 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1543 return;
1547 /**************************************************************************
1548 wrapper for strtok to get the next parameter from a delimited list.
1549 Needed to handle the empty parameter string denoted by "NULL"
1550 *************************************************************************/
1552 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1553 const char *delim, const char **dest,
1554 char **saveptr)
1556 char *ptr;
1558 /* get the next token */
1559 ptr = strtok_r(str, delim, saveptr);
1561 /* a string of 'NULL' is used to represent an empty
1562 parameter because two consecutive delimiters
1563 will not return an empty string. See man strtok(3)
1564 for details */
1565 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1566 ptr = NULL;
1569 if (dest != NULL) {
1570 *dest = talloc_strdup(mem_ctx, ptr);
1573 return ptr;
1576 /********************************************************************************
1577 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1578 string in the form of
1579 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1580 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1581 <Default Data Type>:<Comma Separated list of Files>
1582 *******************************************************************************/
1584 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1585 char *args)
1587 char *str, *str2;
1588 int count = 0;
1589 char *saveptr = NULL;
1590 struct spoolss_StringArray *deps;
1591 const char **file_array = NULL;
1592 int i;
1594 /* fill in the UNISTR fields */
1595 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1596 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1597 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1598 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1599 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1600 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1601 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1603 /* <Comma Separated List of Dependent Files> */
1604 /* save the beginning of the string */
1605 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1606 str = str2;
1608 /* begin to strip out each filename */
1609 str = strtok_r(str, ",", &saveptr);
1611 /* no dependent files, we are done */
1612 if (!str) {
1613 return true;
1616 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1617 if (!deps) {
1618 return false;
1621 while (str != NULL) {
1622 add_string_to_array(deps, str, &file_array, &count);
1623 str = strtok_r(NULL, ",", &saveptr);
1626 deps->string = talloc_zero_array(deps, const char *, count + 1);
1627 if (!deps->string) {
1628 return false;
1631 for (i=0; i < count; i++) {
1632 deps->string[i] = file_array[i];
1635 r->dependent_files = deps;
1637 return true;
1640 /****************************************************************************
1641 ****************************************************************************/
1643 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1644 TALLOC_CTX *mem_ctx,
1645 int argc, const char **argv)
1647 WERROR result;
1648 NTSTATUS status;
1649 uint32_t level = 3;
1650 struct spoolss_AddDriverInfoCtr info_ctr;
1651 struct spoolss_AddDriverInfo3 info3;
1652 const char *arch;
1653 char *driver_args;
1655 /* parse the command arguments */
1656 if (argc != 3 && argc != 4)
1658 printf ("Usage: %s <Environment> \\\n", argv[0]);
1659 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1660 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1661 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1662 printf ("\t[version]\n");
1664 return WERR_OK;
1667 /* Fill in the spoolss_AddDriverInfo3 struct */
1668 ZERO_STRUCT(info3);
1670 arch = cmd_spoolss_get_short_archi(argv[1]);
1671 if (!arch) {
1672 printf ("Error Unknown architechture [%s]\n", argv[1]);
1673 return WERR_INVALID_PARAM;
1676 set_drv_info_3_env(mem_ctx, &info3, arch);
1678 driver_args = talloc_strdup( mem_ctx, argv[2] );
1679 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1681 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1682 return WERR_INVALID_PARAM;
1685 /* if printer driver version specified, override the default version
1686 * used by the architecture. This allows installation of Windows
1687 * 2000 (version 3) printer drivers. */
1688 if (argc == 4)
1690 info3.version = atoi(argv[3]);
1694 info_ctr.level = level;
1695 info_ctr.info.info3 = &info3;
1697 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1698 cli->srv_name_slash,
1699 &info_ctr,
1700 &result);
1701 if (!NT_STATUS_IS_OK(status)) {
1702 return ntstatus_to_werror(status);
1704 if (W_ERROR_IS_OK(result)) {
1705 printf ("Printer Driver %s successfully installed.\n",
1706 info3.driver_name);
1709 return result;
1713 /****************************************************************************
1714 ****************************************************************************/
1716 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1717 TALLOC_CTX *mem_ctx,
1718 int argc, const char **argv)
1720 WERROR result;
1721 struct spoolss_SetPrinterInfoCtr info_ctr;
1722 struct spoolss_SetPrinterInfo2 info2;
1724 /* parse the command arguments */
1725 if (argc != 5)
1727 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1728 return WERR_OK;
1731 /* Fill in the DRIVER_INFO_2 struct */
1732 ZERO_STRUCT(info2);
1734 info2.printername = argv[1];
1735 info2.drivername = argv[3];
1736 info2.sharename = argv[2];
1737 info2.portname = argv[4];
1738 info2.comment = "Created by rpcclient";
1739 info2.printprocessor = "winprint";
1740 info2.datatype = "RAW";
1741 info2.devmode_ptr = 0;
1742 info2.secdesc_ptr = 0;
1743 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1744 info2.priority = 0;
1745 info2.defaultpriority = 0;
1746 info2.starttime = 0;
1747 info2.untiltime = 0;
1749 /* These three fields must not be used by AddPrinter()
1750 as defined in the MS Platform SDK documentation..
1751 --jerry
1752 info2.status = 0;
1753 info2.cjobs = 0;
1754 info2.averageppm = 0;
1757 info_ctr.level = 2;
1758 info_ctr.info.info2 = &info2;
1760 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1761 &info_ctr);
1762 if (W_ERROR_IS_OK(result))
1763 printf ("Printer %s successfully installed.\n", argv[1]);
1765 return result;
1768 /****************************************************************************
1769 ****************************************************************************/
1771 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1772 TALLOC_CTX *mem_ctx,
1773 int argc, const char **argv)
1775 struct policy_handle pol;
1776 WERROR result;
1777 NTSTATUS status;
1778 uint32_t level = 2;
1779 const char *printername;
1780 union spoolss_PrinterInfo info;
1781 struct spoolss_SetPrinterInfoCtr info_ctr;
1782 struct spoolss_SetPrinterInfo2 info2;
1783 struct spoolss_DevmodeContainer devmode_ctr;
1784 struct sec_desc_buf secdesc_ctr;
1786 ZERO_STRUCT(devmode_ctr);
1787 ZERO_STRUCT(secdesc_ctr);
1789 /* parse the command arguments */
1790 if (argc != 3)
1792 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1793 return WERR_OK;
1796 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1798 /* Get a printer handle */
1800 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1801 printername,
1802 PRINTER_ALL_ACCESS,
1803 &pol);
1804 if (!W_ERROR_IS_OK(result))
1805 goto done;
1807 /* Get printer info */
1809 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1810 &pol,
1811 level,
1813 &info);
1814 if (!W_ERROR_IS_OK(result)) {
1815 printf ("Unable to retrieve printer information!\n");
1816 goto done;
1819 /* Set the printer driver */
1821 info2.servername = info.info2.servername;
1822 info2.printername = info.info2.printername;
1823 info2.sharename = info.info2.sharename;
1824 info2.portname = info.info2.portname;
1825 info2.drivername = argv[2];
1826 info2.comment = info.info2.comment;
1827 info2.location = info.info2.location;
1828 info2.devmode_ptr = 0;
1829 info2.sepfile = info.info2.sepfile;
1830 info2.printprocessor = info.info2.printprocessor;
1831 info2.datatype = info.info2.datatype;
1832 info2.parameters = info.info2.parameters;
1833 info2.secdesc_ptr = 0;
1834 info2.attributes = info.info2.attributes;
1835 info2.priority = info.info2.priority;
1836 info2.defaultpriority = info.info2.defaultpriority;
1837 info2.starttime = info.info2.starttime;
1838 info2.untiltime = info.info2.untiltime;
1839 info2.status = info.info2.status;
1840 info2.cjobs = info.info2.cjobs;
1841 info2.averageppm = info.info2.averageppm;
1843 info_ctr.level = 2;
1844 info_ctr.info.info2 = &info2;
1846 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1847 &pol,
1848 &info_ctr,
1849 &devmode_ctr,
1850 &secdesc_ctr,
1851 0, /* command */
1852 &result);
1853 if (!W_ERROR_IS_OK(result)) {
1854 printf("SetPrinter call failed!\n");
1855 goto done;;
1858 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1860 done:
1861 /* Cleanup */
1863 if (is_valid_policy_hnd(&pol))
1864 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1866 return result;
1870 /****************************************************************************
1871 ****************************************************************************/
1873 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1874 TALLOC_CTX *mem_ctx,
1875 int argc, const char **argv)
1877 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1878 NTSTATUS status;
1880 int i;
1881 int vers = -1;
1883 const char *arch = NULL;
1884 uint32_t delete_flags = 0;
1886 /* parse the command arguments */
1887 if (argc < 2 || argc > 4) {
1888 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1889 return WERR_OK;
1892 if (argc >= 3)
1893 arch = argv[2];
1894 if (argc == 4)
1895 vers = atoi (argv[3]);
1897 if (vers >= 0) {
1898 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1901 /* delete the driver for all architectures */
1902 for (i=0; archi_table[i].long_archi; i++) {
1904 if (arch && !strequal( archi_table[i].long_archi, arch))
1905 continue;
1907 if (vers >= 0 && archi_table[i].version != vers)
1908 continue;
1910 /* make the call to remove the driver */
1911 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1912 cli->srv_name_slash,
1913 archi_table[i].long_archi,
1914 argv[1],
1915 delete_flags,
1916 archi_table[i].version,
1917 &result);
1919 if ( !W_ERROR_IS_OK(result) )
1921 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1922 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1923 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1926 else
1928 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1929 archi_table[i].long_archi, archi_table[i].version);
1930 ret = WERR_OK;
1934 return ret;
1938 /****************************************************************************
1939 ****************************************************************************/
1941 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1942 TALLOC_CTX *mem_ctx,
1943 int argc, const char **argv)
1945 WERROR result = WERR_OK;
1946 NTSTATUS status;
1947 int i;
1949 /* parse the command arguments */
1950 if (argc != 2) {
1951 printf ("Usage: %s <driver>\n", argv[0]);
1952 return WERR_OK;
1955 /* delete the driver for all architectures */
1956 for (i=0; archi_table[i].long_archi; i++) {
1957 /* make the call to remove the driver */
1958 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1959 cli->srv_name_slash,
1960 archi_table[i].long_archi,
1961 argv[1],
1962 &result);
1963 if (!NT_STATUS_IS_OK(status)) {
1964 return result;
1966 if ( !W_ERROR_IS_OK(result) ) {
1967 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1968 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1969 argv[1], archi_table[i].long_archi,
1970 W_ERROR_V(result));
1972 } else {
1973 printf ("Driver %s removed for arch [%s].\n", argv[1],
1974 archi_table[i].long_archi);
1978 return result;
1981 /****************************************************************************
1982 ****************************************************************************/
1984 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1985 TALLOC_CTX *mem_ctx,
1986 int argc, const char **argv)
1988 WERROR result;
1989 NTSTATUS status;
1990 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1991 DATA_BLOB buffer;
1992 uint32_t offered;
1993 union spoolss_PrintProcessorDirectoryInfo info;
1994 uint32_t needed;
1996 /* parse the command arguments */
1997 if (argc > 2) {
1998 printf ("Usage: %s [environment]\n", argv[0]);
1999 return WERR_OK;
2002 if (argc == 2) {
2003 environment = argv[1];
2006 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2007 cli->srv_name_slash,
2008 environment,
2010 NULL, /* buffer */
2011 0, /* offered */
2012 NULL, /* info */
2013 &needed,
2014 &result);
2015 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2016 offered = needed;
2017 buffer = data_blob_talloc_zero(mem_ctx, needed);
2019 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
2020 cli->srv_name_slash,
2021 environment,
2023 &buffer,
2024 offered,
2025 &info,
2026 &needed,
2027 &result);
2030 if (W_ERROR_IS_OK(result)) {
2031 printf("%s\n", info.info1.directory_name);
2034 return result;
2037 /****************************************************************************
2038 ****************************************************************************/
2040 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2041 int argc, const char **argv)
2043 struct policy_handle handle;
2044 WERROR werror;
2045 NTSTATUS status;
2046 const char *printername;
2047 union spoolss_AddFormInfo info;
2048 struct spoolss_AddFormInfo1 info1;
2049 struct spoolss_AddFormInfo2 info2;
2050 uint32_t level = 1;
2052 /* Parse the command arguments */
2054 if (argc < 3 || argc > 5) {
2055 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2056 return WERR_OK;
2059 /* Get a printer handle */
2061 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2063 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2064 printername,
2065 PRINTER_ALL_ACCESS,
2066 &handle);
2067 if (!W_ERROR_IS_OK(werror))
2068 goto done;
2070 /* Dummy up some values for the form data */
2072 if (argc == 4) {
2073 level = atoi(argv[3]);
2076 switch (level) {
2077 case 1:
2078 info1.flags = SPOOLSS_FORM_USER;
2079 info1.form_name = argv[2];
2080 info1.size.width = 100;
2081 info1.size.height = 100;
2082 info1.area.left = 0;
2083 info1.area.top = 10;
2084 info1.area.right = 20;
2085 info1.area.bottom = 30;
2087 info.info1 = &info1;
2089 break;
2090 case 2:
2091 info2.flags = SPOOLSS_FORM_USER;
2092 info2.form_name = argv[2];
2093 info2.size.width = 100;
2094 info2.size.height = 100;
2095 info2.area.left = 0;
2096 info2.area.top = 10;
2097 info2.area.right = 20;
2098 info2.area.bottom = 30;
2099 info2.keyword = argv[2];
2100 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2101 info2.mui_dll = NULL;
2102 info2.ressource_id = 0;
2103 info2.display_name = argv[2];
2104 info2.lang_id = 0;
2106 info.info2 = &info2;
2108 break;
2111 /* Add the form */
2114 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2115 &handle,
2116 level,
2117 info,
2118 &werror);
2120 done:
2121 if (is_valid_policy_hnd(&handle))
2122 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2124 return werror;
2127 /****************************************************************************
2128 ****************************************************************************/
2130 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2131 int argc, const char **argv)
2133 struct policy_handle handle;
2134 WERROR werror;
2135 NTSTATUS status;
2136 const char *printername;
2137 union spoolss_AddFormInfo info;
2138 struct spoolss_AddFormInfo1 info1;
2140 /* Parse the command arguments */
2142 if (argc != 3) {
2143 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2144 return WERR_OK;
2147 /* Get a printer handle */
2149 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2151 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2152 printername,
2153 SEC_FLAG_MAXIMUM_ALLOWED,
2154 &handle);
2155 if (!W_ERROR_IS_OK(werror))
2156 goto done;
2158 /* Dummy up some values for the form data */
2160 info1.flags = SPOOLSS_FORM_PRINTER;
2161 info1.size.width = 100;
2162 info1.size.height = 100;
2163 info1.area.left = 0;
2164 info1.area.top = 1000;
2165 info1.area.right = 2000;
2166 info1.area.bottom = 3000;
2167 info1.form_name = argv[2];
2169 info.info1 = &info1;
2171 /* Set the form */
2173 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2174 &handle,
2175 argv[2],
2177 info,
2178 &werror);
2180 done:
2181 if (is_valid_policy_hnd(&handle))
2182 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2184 return werror;
2187 /****************************************************************************
2188 ****************************************************************************/
2190 static const char *get_form_flag(int form_flag)
2192 switch (form_flag) {
2193 case SPOOLSS_FORM_USER:
2194 return "FORM_USER";
2195 case SPOOLSS_FORM_BUILTIN:
2196 return "FORM_BUILTIN";
2197 case SPOOLSS_FORM_PRINTER:
2198 return "FORM_PRINTER";
2199 default:
2200 return "unknown";
2204 /****************************************************************************
2205 ****************************************************************************/
2207 static void display_form_info1(struct spoolss_FormInfo1 *r)
2209 printf("%s\n" \
2210 "\tflag: %s (%d)\n" \
2211 "\twidth: %d, length: %d\n" \
2212 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2213 r->form_name, get_form_flag(r->flags), r->flags,
2214 r->size.width, r->size.height,
2215 r->area.left, r->area.right,
2216 r->area.top, r->area.bottom);
2219 /****************************************************************************
2220 ****************************************************************************/
2222 static void display_form_info2(struct spoolss_FormInfo2 *r)
2224 printf("%s\n" \
2225 "\tflag: %s (%d)\n" \
2226 "\twidth: %d, length: %d\n" \
2227 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2228 r->form_name, get_form_flag(r->flags), r->flags,
2229 r->size.width, r->size.height,
2230 r->area.left, r->area.right,
2231 r->area.top, r->area.bottom);
2232 printf("\tkeyword: %s\n", r->keyword);
2233 printf("\tstring_type: 0x%08x\n", r->string_type);
2234 printf("\tmui_dll: %s\n", r->mui_dll);
2235 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2236 printf("\tdisplay_name: %s\n", r->display_name);
2237 printf("\tlang_id: %d\n", r->lang_id);
2238 printf("\n");
2241 /****************************************************************************
2242 ****************************************************************************/
2244 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2245 int argc, const char **argv)
2247 struct policy_handle handle;
2248 WERROR werror;
2249 NTSTATUS status;
2250 const char *printername;
2251 DATA_BLOB buffer;
2252 uint32_t offered = 0;
2253 union spoolss_FormInfo info;
2254 uint32_t needed;
2255 uint32_t level = 1;
2257 /* Parse the command arguments */
2259 if (argc < 3 || argc > 5) {
2260 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2261 return WERR_OK;
2264 /* Get a printer handle */
2266 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2268 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2269 printername,
2270 SEC_FLAG_MAXIMUM_ALLOWED,
2271 &handle);
2272 if (!W_ERROR_IS_OK(werror))
2273 goto done;
2275 if (argc == 4) {
2276 level = atoi(argv[3]);
2279 /* Get the form */
2281 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2282 &handle,
2283 argv[2],
2284 level,
2285 NULL,
2286 offered,
2287 &info,
2288 &needed,
2289 &werror);
2290 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2291 buffer = data_blob_talloc_zero(mem_ctx, needed);
2292 offered = needed;
2293 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2294 &handle,
2295 argv[2],
2296 level,
2297 &buffer,
2298 offered,
2299 &info,
2300 &needed,
2301 &werror);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 return werror;
2308 switch (level) {
2309 case 1:
2310 display_form_info1(&info.info1);
2311 break;
2312 case 2:
2313 display_form_info2(&info.info2);
2314 break;
2317 done:
2318 if (is_valid_policy_hnd(&handle))
2319 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2321 return werror;
2324 /****************************************************************************
2325 ****************************************************************************/
2327 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2328 TALLOC_CTX *mem_ctx, int argc,
2329 const char **argv)
2331 struct policy_handle handle;
2332 WERROR werror;
2333 NTSTATUS status;
2334 const char *printername;
2336 /* Parse the command arguments */
2338 if (argc != 3) {
2339 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2340 return WERR_OK;
2343 /* Get a printer handle */
2345 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2347 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2348 printername,
2349 SEC_FLAG_MAXIMUM_ALLOWED,
2350 &handle);
2351 if (!W_ERROR_IS_OK(werror))
2352 goto done;
2354 /* Delete the form */
2356 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2357 &handle,
2358 argv[2],
2359 &werror);
2360 if (!NT_STATUS_IS_OK(status)) {
2361 return ntstatus_to_werror(status);
2364 done:
2365 if (is_valid_policy_hnd(&handle))
2366 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2368 return werror;
2371 /****************************************************************************
2372 ****************************************************************************/
2374 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2375 TALLOC_CTX *mem_ctx, int argc,
2376 const char **argv)
2378 struct policy_handle handle;
2379 WERROR werror;
2380 const char *printername;
2381 uint32_t num_forms, level = 1, i;
2382 union spoolss_FormInfo *forms;
2384 /* Parse the command arguments */
2386 if (argc < 2 || argc > 4) {
2387 printf ("Usage: %s <printer> [level]\n", argv[0]);
2388 return WERR_OK;
2391 /* Get a printer handle */
2393 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2395 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2396 printername,
2397 SEC_FLAG_MAXIMUM_ALLOWED,
2398 &handle);
2399 if (!W_ERROR_IS_OK(werror))
2400 goto done;
2402 if (argc == 3) {
2403 level = atoi(argv[2]);
2406 /* Enumerate forms */
2408 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2409 &handle,
2410 level,
2412 &num_forms,
2413 &forms);
2415 if (!W_ERROR_IS_OK(werror))
2416 goto done;
2418 /* Display output */
2420 for (i = 0; i < num_forms; i++) {
2421 switch (level) {
2422 case 1:
2423 display_form_info1(&forms[i].info1);
2424 break;
2425 case 2:
2426 display_form_info2(&forms[i].info2);
2427 break;
2431 done:
2432 if (is_valid_policy_hnd(&handle))
2433 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2435 return werror;
2438 /****************************************************************************
2439 ****************************************************************************/
2441 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2442 TALLOC_CTX *mem_ctx,
2443 int argc, const char **argv)
2445 WERROR result;
2446 NTSTATUS status;
2447 const char *printername;
2448 struct policy_handle pol;
2449 union spoolss_PrinterInfo info;
2450 enum winreg_Type type;
2451 union spoolss_PrinterData data;
2452 DATA_BLOB blob;
2454 /* parse the command arguments */
2455 if (argc < 5) {
2456 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2457 " <value> <data>\n",
2458 argv[0]);
2459 return WERR_OK;
2462 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2464 type = REG_NONE;
2466 if (strequal(argv[2], "string")) {
2467 type = REG_SZ;
2470 if (strequal(argv[2], "binary")) {
2471 type = REG_BINARY;
2474 if (strequal(argv[2], "dword")) {
2475 type = REG_DWORD;
2478 if (strequal(argv[2], "multistring")) {
2479 type = REG_MULTI_SZ;
2482 if (type == REG_NONE) {
2483 printf("Unknown data type: %s\n", argv[2]);
2484 result = WERR_INVALID_PARAM;
2485 goto done;
2488 /* get a printer handle */
2490 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2491 printername,
2492 SEC_FLAG_MAXIMUM_ALLOWED,
2493 &pol);
2494 if (!W_ERROR_IS_OK(result)) {
2495 goto done;
2498 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2499 &pol,
2502 &info);
2503 if (!W_ERROR_IS_OK(result)) {
2504 goto done;
2507 printf("%s\n", current_timestring(mem_ctx, true));
2508 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2510 /* Set the printer data */
2512 switch (type) {
2513 case REG_SZ:
2514 data.string = talloc_strdup(mem_ctx, argv[4]);
2515 W_ERROR_HAVE_NO_MEMORY(data.string);
2516 break;
2517 case REG_DWORD:
2518 data.value = strtoul(argv[4], NULL, 10);
2519 break;
2520 case REG_BINARY:
2521 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2522 break;
2523 case REG_MULTI_SZ: {
2524 int i, num_strings;
2525 const char **strings = NULL;
2527 for (i=4; i<argc; i++) {
2528 if (strcmp(argv[i], "NULL") == 0) {
2529 argv[i] = "";
2531 if (!add_string_to_array(mem_ctx, argv[i],
2532 &strings,
2533 &num_strings)) {
2534 result = WERR_NOMEM;
2535 goto done;
2538 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2539 if (!data.string_array) {
2540 result = WERR_NOMEM;
2541 goto done;
2543 for (i=0; i < num_strings; i++) {
2544 data.string_array[i] = strings[i];
2546 break;
2548 default:
2549 printf("Unknown data type: %s\n", argv[2]);
2550 result = WERR_INVALID_PARAM;
2551 goto done;
2554 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2555 if (!W_ERROR_IS_OK(result)) {
2556 goto done;
2559 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2560 &pol,
2561 argv[3], /* value_name */
2562 type,
2563 blob.data,
2564 blob.length,
2565 &result);
2566 if (!W_ERROR_IS_OK(result)) {
2567 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2568 goto done;
2570 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2572 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2573 &pol,
2576 &info);
2577 if (!W_ERROR_IS_OK(result)) {
2578 goto done;
2581 printf("%s\n", current_timestring(mem_ctx, true));
2582 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2584 done:
2585 /* cleanup */
2586 if (is_valid_policy_hnd(&pol)) {
2587 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2590 return result;
2593 /****************************************************************************
2594 ****************************************************************************/
2596 static void display_job_info1(struct spoolss_JobInfo1 *r)
2598 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2599 r->user_name, r->document_name, r->text_status, r->pages_printed,
2600 r->total_pages);
2603 /****************************************************************************
2604 ****************************************************************************/
2606 static void display_job_info2(struct spoolss_JobInfo2 *r)
2608 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2609 r->position, r->job_id,
2610 r->user_name, r->document_name, r->text_status, r->pages_printed,
2611 r->total_pages, r->size);
2614 /****************************************************************************
2615 ****************************************************************************/
2617 static void display_job_info3(struct spoolss_JobInfo3 *r)
2619 printf("jobid[%d], next_jobid[%d]\n",
2620 r->job_id, r->next_job_id);
2623 /****************************************************************************
2624 ****************************************************************************/
2626 static void display_job_info4(struct spoolss_JobInfo4 *r)
2628 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2629 r->position, r->job_id,
2630 r->user_name, r->document_name, r->text_status, r->pages_printed,
2631 r->total_pages, r->size, r->size_high);
2634 /****************************************************************************
2635 ****************************************************************************/
2637 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2638 TALLOC_CTX *mem_ctx, int argc,
2639 const char **argv)
2641 WERROR result;
2642 uint32_t level = 1, count, i;
2643 const char *printername;
2644 struct policy_handle hnd;
2645 union spoolss_JobInfo *info;
2647 if (argc < 2 || argc > 3) {
2648 printf("Usage: %s printername [level]\n", argv[0]);
2649 return WERR_OK;
2652 if (argc == 3) {
2653 level = atoi(argv[2]);
2656 /* Open printer handle */
2658 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2660 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2661 printername,
2662 SEC_FLAG_MAXIMUM_ALLOWED,
2663 &hnd);
2664 if (!W_ERROR_IS_OK(result))
2665 goto done;
2667 /* Enumerate ports */
2669 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2670 &hnd,
2671 0, /* firstjob */
2672 1000, /* numjobs */
2673 level,
2675 &count,
2676 &info);
2677 if (!W_ERROR_IS_OK(result)) {
2678 goto done;
2681 for (i = 0; i < count; i++) {
2682 switch (level) {
2683 case 1:
2684 display_job_info1(&info[i].info1);
2685 break;
2686 case 2:
2687 display_job_info2(&info[i].info2);
2688 break;
2689 default:
2690 d_printf("unknown info level %d\n", level);
2691 break;
2695 done:
2696 if (is_valid_policy_hnd(&hnd)) {
2697 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2700 return result;
2703 /****************************************************************************
2704 ****************************************************************************/
2706 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2707 TALLOC_CTX *mem_ctx, int argc,
2708 const char **argv)
2710 WERROR result;
2711 const char *printername;
2712 struct policy_handle hnd;
2713 uint32_t job_id;
2714 uint32_t level = 1;
2715 union spoolss_JobInfo info;
2717 if (argc < 3 || argc > 4) {
2718 printf("Usage: %s printername job_id [level]\n", argv[0]);
2719 return WERR_OK;
2722 job_id = atoi(argv[2]);
2724 if (argc == 4) {
2725 level = atoi(argv[3]);
2728 /* Open printer handle */
2730 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2732 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2733 printername,
2734 SEC_FLAG_MAXIMUM_ALLOWED,
2735 &hnd);
2736 if (!W_ERROR_IS_OK(result)) {
2737 goto done;
2740 /* Enumerate ports */
2742 result = rpccli_spoolss_getjob(cli, mem_ctx,
2743 &hnd,
2744 job_id,
2745 level,
2747 &info);
2749 if (!W_ERROR_IS_OK(result)) {
2750 goto done;
2753 switch (level) {
2754 case 1:
2755 display_job_info1(&info.info1);
2756 break;
2757 case 2:
2758 display_job_info2(&info.info2);
2759 break;
2760 case 3:
2761 display_job_info3(&info.info3);
2762 break;
2763 case 4:
2764 display_job_info4(&info.info4);
2765 break;
2766 default:
2767 d_printf("unknown info level %d\n", level);
2768 break;
2771 done:
2772 if (is_valid_policy_hnd(&hnd)) {
2773 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2776 return result;
2779 /****************************************************************************
2780 ****************************************************************************/
2782 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2783 TALLOC_CTX *mem_ctx, int argc,
2784 const char **argv)
2786 WERROR result;
2787 NTSTATUS status;
2788 const char *printername;
2789 struct policy_handle hnd;
2790 uint32_t job_id;
2791 enum spoolss_JobControl command;
2793 if (argc != 4) {
2794 printf("Usage: %s printername job_id command\n", argv[0]);
2795 return WERR_OK;
2798 job_id = atoi(argv[2]);
2799 command = atoi(argv[3]);
2801 /* Open printer handle */
2803 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2805 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2806 printername,
2807 SEC_FLAG_MAXIMUM_ALLOWED,
2808 &hnd);
2809 if (!W_ERROR_IS_OK(result)) {
2810 goto done;
2813 /* Set Job */
2815 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2816 &hnd,
2817 job_id,
2818 NULL,
2819 command,
2820 &result);
2822 if (!W_ERROR_IS_OK(result)) {
2823 goto done;
2826 done:
2827 if (is_valid_policy_hnd(&hnd)) {
2828 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2831 return result;
2834 /****************************************************************************
2835 ****************************************************************************/
2837 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2838 TALLOC_CTX *mem_ctx, int argc,
2839 const char **argv)
2841 WERROR result;
2842 NTSTATUS status;
2843 uint32_t i = 0;
2844 const char *printername;
2845 struct policy_handle hnd;
2846 uint32_t value_offered = 0;
2847 const char *value_name = NULL;
2848 uint32_t value_needed;
2849 enum winreg_Type type;
2850 uint8_t *data = NULL;
2851 uint32_t data_offered = 0;
2852 uint32_t data_needed;
2854 if (argc != 2) {
2855 printf("Usage: %s printername\n", argv[0]);
2856 return WERR_OK;
2859 /* Open printer handle */
2861 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2863 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2864 printername,
2865 SEC_FLAG_MAXIMUM_ALLOWED,
2866 &hnd);
2867 if (!W_ERROR_IS_OK(result)) {
2868 goto done;
2871 /* Enumerate data */
2873 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2874 &hnd,
2876 value_name,
2877 value_offered,
2878 &value_needed,
2879 &type,
2880 data,
2881 data_offered,
2882 &data_needed,
2883 &result);
2885 data_offered = data_needed;
2886 value_offered = value_needed;
2887 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2888 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2890 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2892 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2893 &hnd,
2894 i++,
2895 value_name,
2896 value_offered,
2897 &value_needed,
2898 &type,
2899 data,
2900 data_offered,
2901 &data_needed,
2902 &result);
2903 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2904 struct regval_blob *v;
2906 v = regval_compose(talloc_tos(),
2907 value_name,
2908 type,
2909 data,
2910 data_offered);
2911 if (v == NULL) {
2912 result = WERR_NOMEM;
2913 goto done;
2916 display_reg_value(v);
2917 talloc_free(v);
2921 if (W_ERROR_V(result) == ERRnomoreitems) {
2922 result = W_ERROR(ERRsuccess);
2925 done:
2926 if (is_valid_policy_hnd(&hnd)) {
2927 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2930 return result;
2933 /****************************************************************************
2934 ****************************************************************************/
2936 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2937 TALLOC_CTX *mem_ctx, int argc,
2938 const char **argv)
2940 WERROR result;
2941 uint32_t i;
2942 const char *printername;
2943 struct policy_handle hnd;
2944 uint32_t count;
2945 struct spoolss_PrinterEnumValues *info;
2947 if (argc != 3) {
2948 printf("Usage: %s printername <keyname>\n", argv[0]);
2949 return WERR_OK;
2952 /* Open printer handle */
2954 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2956 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2957 printername,
2958 SEC_FLAG_MAXIMUM_ALLOWED,
2959 &hnd);
2960 if (!W_ERROR_IS_OK(result)) {
2961 goto done;
2964 /* Enumerate subkeys */
2966 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2967 &hnd,
2968 argv[2],
2970 &count,
2971 &info);
2972 if (!W_ERROR_IS_OK(result)) {
2973 goto done;
2976 for (i=0; i < count; i++) {
2977 display_printer_data(info[i].value_name,
2978 info[i].type,
2979 info[i].data->data,
2980 info[i].data->length);
2983 done:
2984 if (is_valid_policy_hnd(&hnd)) {
2985 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2988 return result;
2991 /****************************************************************************
2992 ****************************************************************************/
2994 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2995 TALLOC_CTX *mem_ctx, int argc,
2996 const char **argv)
2998 WERROR result;
2999 const char *printername;
3000 const char *keyname = NULL;
3001 struct policy_handle hnd;
3002 const char **key_buffer = NULL;
3003 int i;
3004 uint32_t offered = 0;
3006 if (argc < 2 || argc > 4) {
3007 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3008 return WERR_OK;
3011 if (argc >= 3) {
3012 keyname = argv[2];
3013 } else {
3014 keyname = "";
3017 if (argc == 4) {
3018 offered = atoi(argv[3]);
3021 /* Open printer handle */
3023 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3025 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3026 printername,
3027 SEC_FLAG_MAXIMUM_ALLOWED,
3028 &hnd);
3029 if (!W_ERROR_IS_OK(result)) {
3030 goto done;
3033 /* Enumerate subkeys */
3035 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3036 &hnd,
3037 keyname,
3038 &key_buffer,
3039 offered);
3041 if (!W_ERROR_IS_OK(result)) {
3042 goto done;
3045 for (i=0; key_buffer && key_buffer[i]; i++) {
3046 printf("%s\n", key_buffer[i]);
3049 done:
3051 if (is_valid_policy_hnd(&hnd)) {
3052 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3055 return result;
3058 /****************************************************************************
3059 ****************************************************************************/
3061 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3062 TALLOC_CTX *mem_ctx, int argc,
3063 const char **argv)
3065 const char *printername;
3066 const char *clientname;
3067 struct policy_handle hnd;
3068 WERROR result;
3069 NTSTATUS status;
3070 struct spoolss_NotifyOption option;
3072 if (argc != 2) {
3073 printf("Usage: %s printername\n", argv[0]);
3074 result = WERR_OK;
3075 goto done;
3078 /* Open printer */
3080 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3082 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3083 printername,
3084 SEC_FLAG_MAXIMUM_ALLOWED,
3085 &hnd);
3086 if (!W_ERROR_IS_OK(result)) {
3087 printf("Error opening %s\n", argv[1]);
3088 goto done;
3091 /* Create spool options */
3093 option.version = 2;
3094 option.count = 2;
3096 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3097 if (option.types == NULL) {
3098 result = WERR_NOMEM;
3099 goto done;
3102 option.types[0].type = PRINTER_NOTIFY_TYPE;
3103 option.types[0].count = 1;
3104 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3105 if (option.types[0].fields == NULL) {
3106 result = WERR_NOMEM;
3107 goto done;
3109 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3111 option.types[1].type = JOB_NOTIFY_TYPE;
3112 option.types[1].count = 1;
3113 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3114 if (option.types[1].fields == NULL) {
3115 result = WERR_NOMEM;
3116 goto done;
3118 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3120 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3121 if (!clientname) {
3122 result = WERR_NOMEM;
3123 goto done;
3126 /* Send rffpcnex */
3128 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3129 &hnd,
3132 clientname,
3133 123,
3134 &option,
3135 &result);
3136 if (!W_ERROR_IS_OK(result)) {
3137 printf("Error rffpcnex %s\n", argv[1]);
3138 goto done;
3141 done:
3142 if (is_valid_policy_hnd(&hnd))
3143 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3145 return result;
3148 /****************************************************************************
3149 ****************************************************************************/
3151 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3152 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3154 union spoolss_PrinterInfo info1, info2;
3155 WERROR werror;
3156 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3158 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3159 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3160 hnd1,
3163 &info1);
3164 if ( !W_ERROR_IS_OK(werror) ) {
3165 printf("failed (%s)\n", win_errstr(werror));
3166 talloc_destroy(mem_ctx);
3167 return false;
3169 printf("ok\n");
3171 printf("Retrieving printer properties for %s...", cli2->desthost);
3172 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3173 hnd2,
3176 &info2);
3177 if ( !W_ERROR_IS_OK(werror) ) {
3178 printf("failed (%s)\n", win_errstr(werror));
3179 talloc_destroy(mem_ctx);
3180 return false;
3182 printf("ok\n");
3184 talloc_destroy(mem_ctx);
3186 return true;
3189 /****************************************************************************
3190 ****************************************************************************/
3192 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3193 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3195 union spoolss_PrinterInfo info1, info2;
3196 WERROR werror;
3197 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3198 struct security_descriptor *sd1, *sd2;
3199 bool result = true;
3202 printf("Retrieving printer security for %s...", cli1->desthost);
3203 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3204 hnd1,
3207 &info1);
3208 if ( !W_ERROR_IS_OK(werror) ) {
3209 printf("failed (%s)\n", win_errstr(werror));
3210 result = false;
3211 goto done;
3213 printf("ok\n");
3215 printf("Retrieving printer security for %s...", cli2->desthost);
3216 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3217 hnd2,
3220 &info2);
3221 if ( !W_ERROR_IS_OK(werror) ) {
3222 printf("failed (%s)\n", win_errstr(werror));
3223 result = false;
3224 goto done;
3226 printf("ok\n");
3229 printf("++ ");
3231 sd1 = info1.info3.secdesc;
3232 sd2 = info2.info3.secdesc;
3234 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3235 printf("NULL secdesc!\n");
3236 result = false;
3237 goto done;
3240 if (!security_descriptor_equal( sd1, sd2 ) ) {
3241 printf("Security Descriptors *not* equal!\n");
3242 result = false;
3243 goto done;
3246 printf("Security descriptors match\n");
3248 done:
3249 talloc_destroy(mem_ctx);
3250 return result;
3254 /****************************************************************************
3255 ****************************************************************************/
3257 extern struct user_auth_info *rpcclient_auth_info;
3259 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3260 TALLOC_CTX *mem_ctx, int argc,
3261 const char **argv)
3263 const char *printername;
3264 char *printername_path = NULL;
3265 struct cli_state *cli_server2 = NULL;
3266 struct rpc_pipe_client *cli2 = NULL;
3267 struct policy_handle hPrinter1, hPrinter2;
3268 NTSTATUS nt_status;
3269 WERROR werror;
3271 if ( argc != 3 ) {
3272 printf("Usage: %s <printer> <server>\n", argv[0]);
3273 return WERR_OK;
3276 printername = argv[1];
3278 /* first get the connection to the remote server */
3280 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3281 NULL, 0,
3282 "IPC$", "IPC",
3283 get_cmdline_auth_info_username(rpcclient_auth_info),
3284 lp_workgroup(),
3285 get_cmdline_auth_info_password(rpcclient_auth_info),
3286 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3287 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3289 if ( !NT_STATUS_IS_OK(nt_status) )
3290 return WERR_GENERAL_FAILURE;
3292 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3293 &cli2);
3294 if (!NT_STATUS_IS_OK(nt_status)) {
3295 printf("failed to open spoolss pipe on server %s (%s)\n",
3296 argv[2], nt_errstr(nt_status));
3297 return WERR_GENERAL_FAILURE;
3300 /* now open up both printers */
3302 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3304 printf("Opening %s...", printername_path);
3306 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3307 printername_path,
3308 PRINTER_ALL_ACCESS,
3309 &hPrinter1);
3310 if ( !W_ERROR_IS_OK(werror) ) {
3311 printf("failed (%s)\n", win_errstr(werror));
3312 goto done;
3314 printf("ok\n");
3316 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3318 printf("Opening %s...", printername_path);
3319 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3320 printername_path,
3321 PRINTER_ALL_ACCESS,
3322 &hPrinter2);
3323 if ( !W_ERROR_IS_OK(werror) ) {
3324 printf("failed (%s)\n", win_errstr(werror));
3325 goto done;
3327 printf("ok\n");
3329 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3330 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3331 #if 0
3332 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3333 #endif
3336 done:
3337 /* cleanup */
3339 printf("Closing printers...");
3340 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3341 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3342 printf("ok\n");
3344 /* close the second remote connection */
3346 cli_shutdown( cli_server2 );
3347 return WERR_OK;
3350 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3352 printf("print_processor_name: %s\n", r->print_processor_name);
3355 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3356 TALLOC_CTX *mem_ctx, int argc,
3357 const char **argv)
3359 WERROR werror;
3360 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3361 uint32_t num_procs, level = 1, i;
3362 union spoolss_PrintProcessorInfo *procs;
3364 /* Parse the command arguments */
3366 if (argc < 1 || argc > 4) {
3367 printf ("Usage: %s [environment] [level]\n", argv[0]);
3368 return WERR_OK;
3371 if (argc >= 2) {
3372 environment = argv[1];
3375 if (argc == 3) {
3376 level = atoi(argv[2]);
3379 /* Enumerate Print Processors */
3381 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3382 cli->srv_name_slash,
3383 environment,
3384 level,
3386 &num_procs,
3387 &procs);
3388 if (!W_ERROR_IS_OK(werror))
3389 goto done;
3391 /* Display output */
3393 for (i = 0; i < num_procs; i++) {
3394 switch (level) {
3395 case 1:
3396 display_proc_info1(&procs[i].info1);
3397 break;
3401 done:
3402 return werror;
3405 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3407 printf("name_array: %s\n", r->name_array);
3410 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3411 TALLOC_CTX *mem_ctx, int argc,
3412 const char **argv)
3414 WERROR werror;
3415 const char *print_processor_name = "winprint";
3416 uint32_t num_procs, level = 1, i;
3417 union spoolss_PrintProcDataTypesInfo *procs;
3419 /* Parse the command arguments */
3421 if (argc < 1 || argc > 4) {
3422 printf ("Usage: %s [environment] [level]\n", argv[0]);
3423 return WERR_OK;
3426 if (argc >= 2) {
3427 print_processor_name = argv[1];
3430 if (argc == 3) {
3431 level = atoi(argv[2]);
3434 /* Enumerate Print Processor Data Types */
3436 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3437 cli->srv_name_slash,
3438 print_processor_name,
3439 level,
3441 &num_procs,
3442 &procs);
3443 if (!W_ERROR_IS_OK(werror))
3444 goto done;
3446 /* Display output */
3448 for (i = 0; i < num_procs; i++) {
3449 switch (level) {
3450 case 1:
3451 display_proc_data_types_info1(&procs[i].info1);
3452 break;
3456 done:
3457 return werror;
3460 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3462 printf("monitor_name: %s\n", r->monitor_name);
3465 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3467 printf("monitor_name: %s\n", r->monitor_name);
3468 printf("environment: %s\n", r->environment);
3469 printf("dll_name: %s\n", r->dll_name);
3472 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3473 TALLOC_CTX *mem_ctx, int argc,
3474 const char **argv)
3476 WERROR werror;
3477 uint32_t count, level = 1, i;
3478 union spoolss_MonitorInfo *info;
3480 /* Parse the command arguments */
3482 if (argc > 2) {
3483 printf("Usage: %s [level]\n", argv[0]);
3484 return WERR_OK;
3487 if (argc == 2) {
3488 level = atoi(argv[1]);
3491 /* Enumerate Print Monitors */
3493 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3494 cli->srv_name_slash,
3495 level,
3497 &count,
3498 &info);
3499 if (!W_ERROR_IS_OK(werror)) {
3500 goto done;
3503 /* Display output */
3505 for (i = 0; i < count; i++) {
3506 switch (level) {
3507 case 1:
3508 display_monitor1(&info[i].info1);
3509 break;
3510 case 2:
3511 display_monitor2(&info[i].info2);
3512 break;
3516 done:
3517 return werror;
3520 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3521 TALLOC_CTX *mem_ctx, int argc,
3522 const char **argv)
3524 WERROR result;
3525 NTSTATUS status;
3526 struct policy_handle handle, gdi_handle;
3527 const char *printername;
3528 struct spoolss_DevmodeContainer devmode_ctr;
3530 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3532 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3533 printername,
3534 SEC_FLAG_MAXIMUM_ALLOWED,
3535 &handle);
3536 if (!W_ERROR_IS_OK(result)) {
3537 return result;
3540 ZERO_STRUCT(devmode_ctr);
3542 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3543 &handle,
3544 &gdi_handle,
3545 &devmode_ctr,
3546 &result);
3547 if (!W_ERROR_IS_OK(result)) {
3548 goto done;
3551 done:
3552 if (is_valid_policy_hnd(&gdi_handle)) {
3553 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3555 if (is_valid_policy_hnd(&handle)) {
3556 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3559 return result;
3562 /* List of commands exported by this module */
3563 struct cmd_set spoolss_commands[] = {
3565 { "SPOOLSS" },
3567 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3568 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3569 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3570 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3571 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3572 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3573 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3574 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3575 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3576 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3577 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3578 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3579 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3580 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3581 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3582 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3583 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3584 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3585 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3586 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3587 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3588 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3589 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3590 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3591 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3592 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3593 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3594 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3595 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3596 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3597 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3598 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3599 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3600 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3601 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3603 { NULL }