WHATSNEW: Update changes.
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blob0341b93c42a0a10785c9b8aa5c11aa01f2804b22
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;
108 uint32_t access_mask = PRINTER_ALL_ACCESS;
110 if (argc < 2) {
111 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
112 return WERR_OK;
115 if (argc >= 3) {
116 sscanf(argv[2], "%x", &access_mask);
119 /* Open the printer handle */
121 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
122 argv[1],
123 access_mask,
124 &hnd);
125 if (W_ERROR_IS_OK(werror)) {
126 printf("Printer %s opened successfully\n", argv[1]);
127 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
129 if (!W_ERROR_IS_OK(werror)) {
130 printf("Error closing printer handle! (%s)\n",
131 get_dos_error_msg(werror));
135 return werror;
139 /****************************************************************************
140 ****************************************************************************/
142 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
144 if (!r)
145 return;
147 printf("\tprintername:[%s]\n", r->printername);
148 printf("\tservername:[%s]\n", r->servername);
149 printf("\tcjobs:[0x%x]\n", r->cjobs);
150 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
151 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
152 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
153 r->time.day, r->time.day_of_week);
154 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
155 r->time.second, r->time.millisecond);
157 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
158 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
160 printf("\tversion:[0x%x]\n", r->version);
161 printf("\tfree_build:[0x%x]\n", r->free_build);
162 printf("\tspooling:[0x%x]\n", r->spooling);
163 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
164 printf("\tsession_counter:[0x%x]\n", r->session_counter);
165 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
166 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
167 printf("\tjob_error:[0x%x]\n", r->job_error);
168 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
169 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
170 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
171 printf("\tchange_id:[0x%x]\n", r->change_id);
172 printf("\tlast_error: %s\n", win_errstr(r->last_error));
173 printf("\tstatus:[0x%x]\n", r->status);
174 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
175 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
176 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
177 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
178 printf("\tref_ic:[0x%x]\n", r->ref_ic);
179 printf("\treserved2:[0x%x]\n", r->reserved2);
180 printf("\treserved3:[0x%x]\n", r->reserved3);
182 printf("\n");
185 /****************************************************************************
186 ****************************************************************************/
188 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
190 printf("\tflags:[0x%x]\n", r->flags);
191 printf("\tname:[%s]\n", r->name);
192 printf("\tdescription:[%s]\n", r->description);
193 printf("\tcomment:[%s]\n", r->comment);
195 printf("\n");
198 /****************************************************************************
199 ****************************************************************************/
201 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
203 printf("\tservername:[%s]\n", r->servername);
204 printf("\tprintername:[%s]\n", r->printername);
205 printf("\tsharename:[%s]\n", r->sharename);
206 printf("\tportname:[%s]\n", r->portname);
207 printf("\tdrivername:[%s]\n", r->drivername);
208 printf("\tcomment:[%s]\n", r->comment);
209 printf("\tlocation:[%s]\n", r->location);
210 printf("\tsepfile:[%s]\n", r->sepfile);
211 printf("\tprintprocessor:[%s]\n", r->printprocessor);
212 printf("\tdatatype:[%s]\n", r->datatype);
213 printf("\tparameters:[%s]\n", r->parameters);
214 printf("\tattributes:[0x%x]\n", r->attributes);
215 printf("\tpriority:[0x%x]\n", r->priority);
216 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
217 printf("\tstarttime:[0x%x]\n", r->starttime);
218 printf("\tuntiltime:[0x%x]\n", r->untiltime);
219 printf("\tstatus:[0x%x]\n", r->status);
220 printf("\tcjobs:[0x%x]\n", r->cjobs);
221 printf("\taverageppm:[0x%x]\n", r->averageppm);
223 if (r->secdesc)
224 display_sec_desc(r->secdesc);
226 printf("\n");
229 /****************************************************************************
230 ****************************************************************************/
232 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
234 display_sec_desc(r->secdesc);
236 printf("\n");
239 /****************************************************************************
240 ****************************************************************************/
242 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
244 printf("\tservername:[%s]\n", r->servername);
245 printf("\tprintername:[%s]\n", r->printername);
246 printf("\tattributes:[0x%x]\n", r->attributes);
247 printf("\n");
250 /****************************************************************************
251 ****************************************************************************/
253 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
255 printf("\tprintername:[%s]\n", r->printername);
256 printf("\tportname:[%s]\n", r->portname);
257 printf("\tattributes:[0x%x]\n", r->attributes);
258 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
259 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
260 printf("\n");
263 /****************************************************************************
264 ****************************************************************************/
266 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
268 printf("\tstatus:[0x%x]\n", r->status);
269 printf("\n");
272 /****************************************************************************
273 ****************************************************************************/
275 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
277 printf("\tguid:[%s]\n", r->guid);
278 printf("\taction:[0x%x]\n", r->action);
279 printf("\n");
282 /****************************************************************************
283 ****************************************************************************/
285 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
286 TALLOC_CTX *mem_ctx,
287 int argc, const char **argv)
289 WERROR result;
290 uint32_t level = 1;
291 union spoolss_PrinterInfo *info;
292 uint32_t i, count;
293 const char *name;
294 uint32_t flags = PRINTER_ENUM_LOCAL;
296 if (argc > 4) {
297 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
298 return WERR_OK;
301 if (argc >= 2) {
302 level = atoi(argv[1]);
305 if (argc >= 3) {
306 name = argv[2];
307 } else {
308 name = cli->srv_name_slash;
311 if (argc == 4) {
312 flags = atoi(argv[3]);
315 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
316 flags,
317 name,
318 level,
320 &count,
321 &info);
322 if (W_ERROR_IS_OK(result)) {
324 if (!count) {
325 printf ("No printers returned.\n");
326 goto done;
329 for (i = 0; i < count; i++) {
330 switch (level) {
331 case 0:
332 display_print_info0(&info[i].info0);
333 break;
334 case 1:
335 display_print_info1(&info[i].info1);
336 break;
337 case 2:
338 display_print_info2(&info[i].info2);
339 break;
340 case 3:
341 display_print_info3(&info[i].info3);
342 break;
343 case 4:
344 display_print_info4(&info[i].info4);
345 break;
346 case 5:
347 display_print_info5(&info[i].info5);
348 break;
349 case 6:
350 display_print_info6(&info[i].info6);
351 break;
352 default:
353 printf("unknown info level %d\n", level);
354 goto done;
358 done:
360 return result;
363 /****************************************************************************
364 ****************************************************************************/
366 static void display_port_info_1(struct spoolss_PortInfo1 *r)
368 printf("\tPort Name:\t[%s]\n", r->port_name);
371 /****************************************************************************
372 ****************************************************************************/
374 static void display_port_info_2(struct spoolss_PortInfo2 *r)
376 printf("\tPort Name:\t[%s]\n", r->port_name);
377 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
378 printf("\tDescription:\t[%s]\n", r->description);
379 printf("\tPort Type:\t" );
380 if (r->port_type) {
381 int comma = 0; /* hack */
382 printf( "[" );
383 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
384 printf( "Read" );
385 comma = 1;
387 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
388 printf( "%sWrite", comma ? ", " : "" );
389 comma = 1;
391 /* These two have slightly different interpretations
392 on 95/98/ME but I'm disregarding that for now */
393 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
394 printf( "%sRedirected", comma ? ", " : "" );
395 comma = 1;
397 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
398 printf( "%sNet-Attached", comma ? ", " : "" );
400 printf( "]\n" );
401 } else {
402 printf( "[Unset]\n" );
404 printf("\tReserved:\t[%d]\n", r->reserved);
405 printf("\n");
408 /****************************************************************************
409 ****************************************************************************/
411 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
412 TALLOC_CTX *mem_ctx, int argc,
413 const char **argv)
415 WERROR result;
416 uint32_t level = 1;
417 uint32_t count;
418 union spoolss_PortInfo *info;
420 if (argc > 2) {
421 printf("Usage: %s [level]\n", argv[0]);
422 return WERR_OK;
425 if (argc == 2) {
426 level = atoi(argv[1]);
429 /* Enumerate ports */
431 result = rpccli_spoolss_enumports(cli, mem_ctx,
432 cli->srv_name_slash,
433 level,
435 &count,
436 &info);
437 if (W_ERROR_IS_OK(result)) {
438 int i;
440 for (i = 0; i < count; i++) {
441 switch (level) {
442 case 1:
443 display_port_info_1(&info[i].info1);
444 break;
445 case 2:
446 display_port_info_2(&info[i].info2);
447 break;
448 default:
449 printf("unknown info level %d\n", level);
450 break;
455 return result;
458 /****************************************************************************
459 ****************************************************************************/
461 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
462 TALLOC_CTX *mem_ctx,
463 int argc, const char **argv)
465 struct policy_handle pol;
466 WERROR result;
467 NTSTATUS status;
468 uint32_t info_level = 2;
469 union spoolss_PrinterInfo info;
470 struct spoolss_SetPrinterInfoCtr info_ctr;
471 struct spoolss_SetPrinterInfo2 info2;
472 const char *printername, *comment = NULL;
473 struct spoolss_DevmodeContainer devmode_ctr;
474 struct sec_desc_buf secdesc_ctr;
476 if (argc == 1 || argc > 3) {
477 printf("Usage: %s printername comment\n", argv[0]);
479 return WERR_OK;
482 /* Open a printer handle */
483 if (argc == 3) {
484 comment = argv[2];
487 ZERO_STRUCT(devmode_ctr);
488 ZERO_STRUCT(secdesc_ctr);
490 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
492 /* get a printer handle */
493 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
494 printername,
495 PRINTER_ALL_ACCESS,
496 &pol);
497 if (!W_ERROR_IS_OK(result))
498 goto done;
500 /* Get printer info */
501 result = rpccli_spoolss_getprinter(cli, mem_ctx,
502 &pol,
503 info_level,
505 &info);
506 if (!W_ERROR_IS_OK(result))
507 goto done;
510 /* Modify the comment. */
511 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
512 info2.comment = comment;
514 info_ctr.level = 2;
515 info_ctr.info.info2 = &info2;
517 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
518 &pol,
519 &info_ctr,
520 &devmode_ctr,
521 &secdesc_ctr,
522 0, /* command */
523 &result);
524 if (W_ERROR_IS_OK(result))
525 printf("Success in setting comment.\n");
527 done:
528 if (is_valid_policy_hnd(&pol))
529 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
531 return result;
534 /****************************************************************************
535 ****************************************************************************/
537 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
538 TALLOC_CTX *mem_ctx,
539 int argc, const char **argv)
541 struct policy_handle pol;
542 WERROR result;
543 NTSTATUS status;
544 uint32_t info_level = 2;
545 union spoolss_PrinterInfo info;
546 const char *printername,
547 *new_printername = NULL;
548 struct spoolss_SetPrinterInfoCtr info_ctr;
549 struct spoolss_SetPrinterInfo2 info2;
550 struct spoolss_DevmodeContainer devmode_ctr;
551 struct sec_desc_buf secdesc_ctr;
553 ZERO_STRUCT(devmode_ctr);
554 ZERO_STRUCT(secdesc_ctr);
556 if (argc == 1 || argc > 3) {
557 printf("Usage: %s printername new_printername\n", argv[0]);
559 return WERR_OK;
562 /* Open a printer handle */
563 if (argc == 3) {
564 new_printername = argv[2];
567 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
569 /* get a printer handle */
570 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
571 printername,
572 PRINTER_ALL_ACCESS,
573 &pol);
574 if (!W_ERROR_IS_OK(result))
575 goto done;
577 /* Get printer info */
578 result = rpccli_spoolss_getprinter(cli, mem_ctx,
579 &pol,
580 info_level,
582 &info);
583 if (!W_ERROR_IS_OK(result))
584 goto done;
586 /* Modify the printername. */
587 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
588 info2.printername = new_printername;
590 info_ctr.level = 2;
591 info_ctr.info.info2 = &info2;
593 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
594 &pol,
595 &info_ctr,
596 &devmode_ctr,
597 &secdesc_ctr,
598 0, /* command */
599 &result);
600 if (W_ERROR_IS_OK(result))
601 printf("Success in setting printername.\n");
603 done:
604 if (is_valid_policy_hnd(&pol))
605 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
607 return result;
610 /****************************************************************************
611 ****************************************************************************/
613 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
614 TALLOC_CTX *mem_ctx,
615 int argc, const char **argv)
617 struct policy_handle pol;
618 WERROR result;
619 uint32_t level = 1;
620 const char *printername;
621 union spoolss_PrinterInfo info;
623 if (argc == 1 || argc > 3) {
624 printf("Usage: %s <printername> [level]\n", argv[0]);
625 return WERR_OK;
628 /* Open a printer handle */
629 if (argc == 3) {
630 level = atoi(argv[2]);
633 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
635 /* get a printer handle */
637 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
638 printername,
639 SEC_FLAG_MAXIMUM_ALLOWED,
640 &pol);
641 if (!W_ERROR_IS_OK(result)) {
642 goto done;
645 /* Get printer info */
647 result = rpccli_spoolss_getprinter(cli, mem_ctx,
648 &pol,
649 level,
651 &info);
652 if (!W_ERROR_IS_OK(result)) {
653 goto done;
656 /* Display printer info */
657 switch (level) {
658 case 0:
659 display_print_info0(&info.info0);
660 break;
661 case 1:
662 display_print_info1(&info.info1);
663 break;
664 case 2:
665 display_print_info2(&info.info2);
666 break;
667 case 3:
668 display_print_info3(&info.info3);
669 break;
670 case 4:
671 display_print_info4(&info.info4);
672 break;
673 case 5:
674 display_print_info5(&info.info5);
675 break;
676 case 6:
677 display_print_info6(&info.info6);
678 break;
679 case 7:
680 display_print_info7(&info.info7);
681 break;
682 default:
683 printf("unknown info level %d\n", level);
684 break;
686 done:
687 if (is_valid_policy_hnd(&pol)) {
688 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
691 return result;
694 /****************************************************************************
695 ****************************************************************************/
697 static void display_reg_value(struct regval_blob *value)
699 const char *text = NULL;
700 DATA_BLOB blob;
702 switch(regval_type(value)) {
703 case REG_DWORD:
704 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
705 *((uint32_t *) regval_data_p(value)));
706 break;
707 case REG_SZ:
708 blob = data_blob_const(regval_data_p(value), regval_size(value));
709 pull_reg_sz(talloc_tos(), &blob, &text);
710 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
711 break;
712 case REG_BINARY: {
713 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
714 size_t i, len;
715 printf("%s: REG_BINARY:", regval_name(value));
716 len = strlen(hex);
717 for (i=0; i<len; i++) {
718 if (hex[i] == '\0') {
719 break;
721 if (i%40 == 0) {
722 putchar('\n');
724 putchar(hex[i]);
726 TALLOC_FREE(hex);
727 putchar('\n');
728 break;
730 case REG_MULTI_SZ: {
731 uint32_t i;
732 const char **values;
733 blob = data_blob_const(regval_data_p(value), regval_size(value));
735 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
736 d_printf("pull_reg_multi_sz failed\n");
737 break;
740 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
741 for (i=0; values[i] != NULL; i++) {
742 d_printf("%s\n", values[i]);
744 TALLOC_FREE(values);
745 break;
747 default:
748 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
753 /****************************************************************************
754 ****************************************************************************/
756 static void display_printer_data(const char *v,
757 enum winreg_Type type,
758 uint8_t *data,
759 uint32_t length)
761 int i;
762 union spoolss_PrinterData r;
763 DATA_BLOB blob = data_blob_const(data, length);
764 WERROR result;
766 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
767 if (!W_ERROR_IS_OK(result)) {
768 return;
771 switch (type) {
772 case REG_DWORD:
773 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
774 break;
775 case REG_SZ:
776 printf("%s: REG_SZ: %s\n", v, r.string);
777 break;
778 case REG_BINARY: {
779 char *hex = hex_encode_talloc(NULL,
780 r.binary.data, r.binary.length);
781 size_t len;
782 printf("%s: REG_BINARY:", v);
783 len = strlen(hex);
784 for (i=0; i<len; i++) {
785 if (hex[i] == '\0') {
786 break;
788 if (i%40 == 0) {
789 putchar('\n');
791 putchar(hex[i]);
793 TALLOC_FREE(hex);
794 putchar('\n');
795 break;
797 case REG_MULTI_SZ:
798 printf("%s: REG_MULTI_SZ: ", v);
799 for (i=0; r.string_array[i] != NULL; i++) {
800 printf("%s ", r.string_array[i]);
802 printf("\n");
803 break;
804 default:
805 printf("%s: unknown type 0x%02x:\n", v, type);
806 break;
810 /****************************************************************************
811 ****************************************************************************/
813 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
814 TALLOC_CTX *mem_ctx,
815 int argc, const char **argv)
817 struct policy_handle pol;
818 WERROR result;
819 fstring printername;
820 const char *valuename;
821 enum winreg_Type type;
822 uint8_t *data;
823 uint32_t needed;
825 if (argc != 3) {
826 printf("Usage: %s <printername> <valuename>\n", argv[0]);
827 printf("<printername> of . queries print server\n");
828 return WERR_OK;
830 valuename = argv[2];
832 /* Open a printer handle */
834 if (strncmp(argv[1], ".", sizeof(".")) == 0)
835 fstrcpy(printername, cli->srv_name_slash);
836 else
837 slprintf(printername, sizeof(printername)-1, "%s\\%s",
838 cli->srv_name_slash, argv[1]);
840 /* get a printer handle */
842 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
843 printername,
844 SEC_FLAG_MAXIMUM_ALLOWED,
845 &pol);
846 if (!W_ERROR_IS_OK(result))
847 goto done;
849 /* Get printer info */
851 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
852 &pol,
853 valuename,
855 &type,
856 &needed,
857 &data);
858 if (!W_ERROR_IS_OK(result))
859 goto done;
861 /* Display printer data */
863 display_printer_data(valuename, type, data, needed);
865 done:
866 if (is_valid_policy_hnd(&pol))
867 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
869 return result;
872 /****************************************************************************
873 ****************************************************************************/
875 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
876 TALLOC_CTX *mem_ctx,
877 int argc, const char **argv)
879 struct policy_handle pol;
880 WERROR result;
881 NTSTATUS status;
882 fstring printername;
883 const char *valuename, *keyname;
885 enum winreg_Type type;
886 uint8_t *data = NULL;
887 uint32_t offered = 0;
888 uint32_t needed;
890 if (argc != 4) {
891 printf("Usage: %s <printername> <keyname> <valuename>\n",
892 argv[0]);
893 printf("<printername> of . queries print server\n");
894 return WERR_OK;
896 valuename = argv[3];
897 keyname = argv[2];
899 /* Open a printer handle */
901 if (strncmp(argv[1], ".", sizeof(".")) == 0)
902 fstrcpy(printername, cli->srv_name_slash);
903 else
904 slprintf(printername, sizeof(printername)-1, "%s\\%s",
905 cli->srv_name_slash, argv[1]);
907 /* get a printer handle */
909 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
910 printername,
911 SEC_FLAG_MAXIMUM_ALLOWED,
912 &pol);
913 if (!W_ERROR_IS_OK(result))
914 goto done;
916 /* Get printer info */
918 data = talloc_zero_array(mem_ctx, uint8_t, offered);
919 if (!data) {
920 goto done;
923 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
924 &pol,
925 keyname,
926 valuename,
927 &type,
928 data,
929 offered,
930 &needed,
931 &result);
932 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
933 offered = needed;
934 data = talloc_zero_array(mem_ctx, uint8_t, offered);
935 if (!data) {
936 goto done;
938 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
939 &pol,
940 keyname,
941 valuename,
942 &type,
943 data,
944 offered,
945 &needed,
946 &result);
949 if (!NT_STATUS_IS_OK(status)) {
950 goto done;
953 if (!W_ERROR_IS_OK(result))
954 goto done;
956 /* Display printer data */
958 display_printer_data(valuename, type, data, needed);
961 done:
962 if (is_valid_policy_hnd(&pol))
963 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
965 return result;
968 /****************************************************************************
969 ****************************************************************************/
971 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
973 if (!r) {
974 return;
977 printf("Printer Driver Info 1:\n");
978 printf("\tDriver Name: [%s]\n", r->driver_name);
979 printf("\n");
982 /****************************************************************************
983 ****************************************************************************/
985 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
987 if (!r) {
988 return;
991 printf("Printer Driver Info 2:\n");
992 printf("\tVersion: [%x]\n", r->version);
993 printf("\tDriver Name: [%s]\n", r->driver_name);
994 printf("\tArchitecture: [%s]\n", r->architecture);
995 printf("\tDriver Path: [%s]\n", r->driver_path);
996 printf("\tDatafile: [%s]\n", r->data_file);
997 printf("\tConfigfile: [%s]\n", r->config_file);
998 printf("\n");
1001 /****************************************************************************
1002 ****************************************************************************/
1004 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1006 int i;
1008 if (!r) {
1009 return;
1012 printf("Printer Driver Info 3:\n");
1013 printf("\tVersion: [%x]\n", r->version);
1014 printf("\tDriver Name: [%s]\n", r->driver_name);
1015 printf("\tArchitecture: [%s]\n", r->architecture);
1016 printf("\tDriver Path: [%s]\n", r->driver_path);
1017 printf("\tDatafile: [%s]\n", r->data_file);
1018 printf("\tConfigfile: [%s]\n", r->config_file);
1019 printf("\tHelpfile: [%s]\n", r->help_file);
1021 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1022 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1025 printf("\tMonitorname: [%s]\n", r->monitor_name);
1026 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1027 printf("\n");
1030 /****************************************************************************
1031 ****************************************************************************/
1033 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1035 int i;
1037 if (!r) {
1038 return;
1041 printf("Printer Driver Info 4:\n");
1042 printf("\tVersion: [%x]\n", r->version);
1043 printf("\tDriver Name: [%s]\n", r->driver_name);
1044 printf("\tArchitecture: [%s]\n", r->architecture);
1045 printf("\tDriver Path: [%s]\n", r->driver_path);
1046 printf("\tDatafile: [%s]\n", r->data_file);
1047 printf("\tConfigfile: [%s]\n", r->config_file);
1048 printf("\tHelpfile: [%s]\n", r->help_file);
1050 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1051 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1054 printf("\tMonitorname: [%s]\n", r->monitor_name);
1055 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1057 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1058 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1060 printf("\n");
1063 /****************************************************************************
1064 ****************************************************************************/
1066 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1068 if (!r) {
1069 return;
1072 printf("Printer Driver Info 5:\n");
1073 printf("\tVersion: [%x]\n", r->version);
1074 printf("\tDriver Name: [%s]\n", r->driver_name);
1075 printf("\tArchitecture: [%s]\n", r->architecture);
1076 printf("\tDriver Path: [%s]\n", r->driver_path);
1077 printf("\tDatafile: [%s]\n", r->data_file);
1078 printf("\tConfigfile: [%s]\n", r->config_file);
1079 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1080 printf("\tConfig Version: [0x%x]\n", r->config_version);
1081 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1082 printf("\n");
1085 /****************************************************************************
1086 ****************************************************************************/
1088 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1090 int i;
1092 if (!r) {
1093 return;
1096 printf("Printer Driver Info 6:\n");
1097 printf("\tVersion: [%x]\n", r->version);
1098 printf("\tDriver Name: [%s]\n", r->driver_name);
1099 printf("\tArchitecture: [%s]\n", r->architecture);
1100 printf("\tDriver Path: [%s]\n", r->driver_path);
1101 printf("\tDatafile: [%s]\n", r->data_file);
1102 printf("\tConfigfile: [%s]\n", r->config_file);
1103 printf("\tHelpfile: [%s]\n", r->help_file);
1105 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1106 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1109 printf("\tMonitorname: [%s]\n", r->monitor_name);
1110 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1112 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1113 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1116 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1117 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1118 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1119 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1120 printf("\tHardware ID: [%s]\n", r->hardware_id);
1121 printf("\tProvider: [%s]\n", r->provider);
1123 printf("\n");
1126 /****************************************************************************
1127 ****************************************************************************/
1129 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1131 int i;
1133 if (!r) {
1134 return;
1137 printf("Printer Driver Info 8:\n");
1138 printf("\tVersion: [%x]\n", r->version);
1139 printf("\tDriver Name: [%s]\n", r->driver_name);
1140 printf("\tArchitecture: [%s]\n", r->architecture);
1141 printf("\tDriver Path: [%s]\n", r->driver_path);
1142 printf("\tDatafile: [%s]\n", r->data_file);
1143 printf("\tConfigfile: [%s]\n", r->config_file);
1144 printf("\tHelpfile: [%s]\n", r->help_file);
1145 printf("\tMonitorname: [%s]\n", r->monitor_name);
1146 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1148 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1149 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1152 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1153 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1156 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1157 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1158 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1159 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1160 printf("\tHardware ID: [%s]\n", r->hardware_id);
1161 printf("\tProvider: [%s]\n", r->provider);
1162 printf("\tPrint Processor: [%s]\n", r->print_processor);
1163 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1164 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1165 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1167 printf("\tInf Path: [%s]\n", r->inf_path);
1168 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1169 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1170 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1172 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1173 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1174 (long long unsigned int)r->min_inbox_driver_ver_version);
1176 printf("\n");
1179 /****************************************************************************
1180 ****************************************************************************/
1182 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1183 TALLOC_CTX *mem_ctx,
1184 int argc, const char **argv)
1186 struct policy_handle pol;
1187 WERROR werror;
1188 uint32_t level = 3;
1189 const char *printername;
1190 uint32_t i;
1191 bool success = false;
1192 union spoolss_DriverInfo info;
1193 uint32_t server_major_version;
1194 uint32_t server_minor_version;
1196 if ((argc == 1) || (argc > 3)) {
1197 printf("Usage: %s <printername> [level]\n", argv[0]);
1198 return WERR_OK;
1201 /* get the arguments need to open the printer handle */
1203 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1205 if (argc == 3) {
1206 level = atoi(argv[2]);
1209 /* Open a printer handle */
1211 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1212 printername,
1213 PRINTER_ACCESS_USE,
1214 &pol);
1215 if (!W_ERROR_IS_OK(werror)) {
1216 printf("Error opening printer handle for %s!\n", printername);
1217 return werror;
1220 /* loop through and print driver info level for each architecture */
1222 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1224 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1225 &pol,
1226 archi_table[i].long_archi,
1227 level,
1228 0, /* offered */
1229 archi_table[i].version,
1231 &info,
1232 &server_major_version,
1233 &server_minor_version);
1234 if (!W_ERROR_IS_OK(werror)) {
1235 continue;
1238 /* need at least one success */
1240 success = true;
1242 printf("\n[%s]\n", archi_table[i].long_archi);
1244 switch (level) {
1245 case 1:
1246 display_print_driver1(&info.info1);
1247 break;
1248 case 2:
1249 display_print_driver2(&info.info2);
1250 break;
1251 case 3:
1252 display_print_driver3(&info.info3);
1253 break;
1254 case 4:
1255 display_print_driver4(&info.info4);
1256 break;
1257 case 5:
1258 display_print_driver5(&info.info5);
1259 break;
1260 case 6:
1261 display_print_driver6(&info.info6);
1262 break;
1263 case 8:
1264 display_print_driver8(&info.info8);
1265 break;
1266 default:
1267 printf("unknown info level %d\n", level);
1268 break;
1272 /* Cleanup */
1274 if (is_valid_policy_hnd(&pol)) {
1275 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1278 if (success) {
1279 werror = WERR_OK;
1282 return werror;
1285 /****************************************************************************
1286 ****************************************************************************/
1288 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1289 TALLOC_CTX *mem_ctx,
1290 const char *architecture,
1291 uint32_t level)
1293 WERROR werror;
1294 uint32_t count = 0;
1295 union spoolss_DriverInfo *info = NULL;
1296 uint32_t j;
1298 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1299 cli->srv_name_slash,
1300 architecture,
1301 level,
1303 &count,
1304 &info);
1306 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1307 printf("Server does not support environment [%s]\n",
1308 architecture);
1309 return WERR_OK;
1312 if (count == 0) {
1313 return WERR_OK;
1316 if (!W_ERROR_IS_OK(werror)) {
1317 printf("Error getting driver for environment [%s] - %s\n",
1318 architecture, win_errstr(werror));
1319 return werror;
1322 printf("\n[%s]\n", architecture);
1324 switch (level) {
1325 case 1:
1326 for (j=0; j < count; j++) {
1327 display_print_driver1(&info[j].info1);
1329 break;
1330 case 2:
1331 for (j=0; j < count; j++) {
1332 display_print_driver2(&info[j].info2);
1334 break;
1335 case 3:
1336 for (j=0; j < count; j++) {
1337 display_print_driver3(&info[j].info3);
1339 break;
1340 case 4:
1341 for (j=0; j < count; j++) {
1342 display_print_driver4(&info[j].info4);
1344 break;
1345 case 5:
1346 for (j=0; j < count; j++) {
1347 display_print_driver5(&info[j].info5);
1349 break;
1350 case 6:
1351 for (j=0; j < count; j++) {
1352 display_print_driver6(&info[j].info6);
1354 break;
1355 case 8:
1356 for (j=0; j < count; j++) {
1357 display_print_driver8(&info[j].info8);
1359 break;
1360 default:
1361 printf("unknown info level %d\n", level);
1362 return WERR_UNKNOWN_LEVEL;
1365 return werror;
1368 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1369 TALLOC_CTX *mem_ctx,
1370 int argc, const char **argv)
1372 WERROR werror = WERR_OK;
1373 uint32_t level = 1;
1374 uint32_t i;
1375 const char *architecture = NULL;
1377 if (argc > 3) {
1378 printf("Usage: enumdrivers [level] [architecture]\n");
1379 return WERR_OK;
1382 if (argc >= 2) {
1383 level = atoi(argv[1]);
1386 if (argc == 3) {
1387 architecture = argv[2];
1390 if (architecture) {
1391 return enum_driver_by_architecture(cli, mem_ctx,
1392 architecture,
1393 level);
1396 /* loop through and print driver info level for each architecture */
1397 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1398 /* check to see if we already asked for this architecture string */
1400 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1401 continue;
1404 werror = enum_driver_by_architecture(cli, mem_ctx,
1405 archi_table[i].long_archi,
1406 level);
1407 if (!W_ERROR_IS_OK(werror)) {
1408 break;
1412 return werror;
1415 /****************************************************************************
1416 ****************************************************************************/
1418 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1420 printf("\tDirectory Name:[%s]\n", r->directory_name);
1423 /****************************************************************************
1424 ****************************************************************************/
1426 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1427 TALLOC_CTX *mem_ctx,
1428 int argc, const char **argv)
1430 WERROR result;
1431 NTSTATUS status;
1432 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1433 DATA_BLOB buffer;
1434 uint32_t offered;
1435 union spoolss_DriverDirectoryInfo info;
1436 uint32_t needed;
1438 if (argc > 2) {
1439 printf("Usage: %s [environment]\n", argv[0]);
1440 return WERR_OK;
1443 /* Get the arguments need to open the printer handle */
1445 if (argc == 2) {
1446 env = argv[1];
1449 /* Get the directory. Only use Info level 1 */
1451 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1452 cli->srv_name_slash,
1453 env,
1455 NULL, /* buffer */
1456 0, /* offered */
1457 NULL, /* info */
1458 &needed,
1459 &result);
1460 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1461 offered = needed;
1462 buffer = data_blob_talloc_zero(mem_ctx, needed);
1464 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1465 cli->srv_name_slash,
1466 env,
1468 &buffer,
1469 offered,
1470 &info,
1471 &needed,
1472 &result);
1475 if (W_ERROR_IS_OK(result)) {
1476 display_printdriverdir_1(&info.info1);
1479 return result;
1482 /****************************************************************************
1483 ****************************************************************************/
1485 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1486 struct spoolss_AddDriverInfo3 *info,
1487 const char *arch)
1490 int i;
1492 for (i=0; archi_table[i].long_archi != NULL; i++)
1494 if (strcmp(arch, archi_table[i].short_archi) == 0)
1496 info->version = archi_table[i].version;
1497 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1498 break;
1502 if (archi_table[i].long_archi == NULL)
1504 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1507 return;
1511 /**************************************************************************
1512 wrapper for strtok to get the next parameter from a delimited list.
1513 Needed to handle the empty parameter string denoted by "NULL"
1514 *************************************************************************/
1516 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1517 const char *delim, const char **dest,
1518 char **saveptr)
1520 char *ptr;
1522 /* get the next token */
1523 ptr = strtok_r(str, delim, saveptr);
1525 /* a string of 'NULL' is used to represent an empty
1526 parameter because two consecutive delimiters
1527 will not return an empty string. See man strtok(3)
1528 for details */
1529 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1530 ptr = NULL;
1533 if (dest != NULL) {
1534 *dest = talloc_strdup(mem_ctx, ptr);
1537 return ptr;
1540 /********************************************************************************
1541 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1542 string in the form of
1543 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1544 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1545 <Default Data Type>:<Comma Separated list of Files>
1546 *******************************************************************************/
1548 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1549 char *args)
1551 char *str, *str2;
1552 int count = 0;
1553 char *saveptr = NULL;
1554 struct spoolss_StringArray *deps;
1555 const char **file_array = NULL;
1556 int i;
1558 /* fill in the UNISTR fields */
1559 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1560 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1561 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1562 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1563 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1564 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1565 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1567 /* <Comma Separated List of Dependent Files> */
1568 /* save the beginning of the string */
1569 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1570 str = str2;
1572 /* begin to strip out each filename */
1573 str = strtok_r(str, ",", &saveptr);
1575 /* no dependent files, we are done */
1576 if (!str) {
1577 return true;
1580 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1581 if (!deps) {
1582 return false;
1585 while (str != NULL) {
1586 add_string_to_array(deps, str, &file_array, &count);
1587 str = strtok_r(NULL, ",", &saveptr);
1590 deps->string = talloc_zero_array(deps, const char *, count + 1);
1591 if (!deps->string) {
1592 return false;
1595 for (i=0; i < count; i++) {
1596 deps->string[i] = file_array[i];
1599 r->dependent_files = deps;
1601 return true;
1604 /****************************************************************************
1605 ****************************************************************************/
1607 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1608 TALLOC_CTX *mem_ctx,
1609 int argc, const char **argv)
1611 WERROR result;
1612 NTSTATUS status;
1613 uint32_t level = 3;
1614 struct spoolss_AddDriverInfoCtr info_ctr;
1615 struct spoolss_AddDriverInfo3 info3;
1616 const char *arch;
1617 char *driver_args;
1619 /* parse the command arguments */
1620 if (argc != 3 && argc != 4)
1622 printf ("Usage: %s <Environment> \\\n", argv[0]);
1623 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1624 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1625 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1626 printf ("\t[version]\n");
1628 return WERR_OK;
1631 /* Fill in the spoolss_AddDriverInfo3 struct */
1632 ZERO_STRUCT(info3);
1634 arch = cmd_spoolss_get_short_archi(argv[1]);
1635 if (!arch) {
1636 printf ("Error Unknown architechture [%s]\n", argv[1]);
1637 return WERR_INVALID_PARAM;
1640 set_drv_info_3_env(mem_ctx, &info3, arch);
1642 driver_args = talloc_strdup( mem_ctx, argv[2] );
1643 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1645 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1646 return WERR_INVALID_PARAM;
1649 /* if printer driver version specified, override the default version
1650 * used by the architecture. This allows installation of Windows
1651 * 2000 (version 3) printer drivers. */
1652 if (argc == 4)
1654 info3.version = atoi(argv[3]);
1658 info_ctr.level = level;
1659 info_ctr.info.info3 = &info3;
1661 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1662 cli->srv_name_slash,
1663 &info_ctr,
1664 &result);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 return ntstatus_to_werror(status);
1668 if (W_ERROR_IS_OK(result)) {
1669 printf ("Printer Driver %s successfully installed.\n",
1670 info3.driver_name);
1673 return result;
1677 /****************************************************************************
1678 ****************************************************************************/
1680 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1681 TALLOC_CTX *mem_ctx,
1682 int argc, const char **argv)
1684 WERROR result;
1685 struct spoolss_SetPrinterInfoCtr info_ctr;
1686 struct spoolss_SetPrinterInfo2 info2;
1688 /* parse the command arguments */
1689 if (argc != 5)
1691 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1692 return WERR_OK;
1695 /* Fill in the DRIVER_INFO_2 struct */
1696 ZERO_STRUCT(info2);
1698 info2.printername = argv[1];
1699 info2.drivername = argv[3];
1700 info2.sharename = argv[2];
1701 info2.portname = argv[4];
1702 info2.comment = "Created by rpcclient";
1703 info2.printprocessor = "winprint";
1704 info2.datatype = "RAW";
1705 info2.devmode_ptr = 0;
1706 info2.secdesc_ptr = 0;
1707 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1708 info2.priority = 0;
1709 info2.defaultpriority = 0;
1710 info2.starttime = 0;
1711 info2.untiltime = 0;
1713 /* These three fields must not be used by AddPrinter()
1714 as defined in the MS Platform SDK documentation..
1715 --jerry
1716 info2.status = 0;
1717 info2.cjobs = 0;
1718 info2.averageppm = 0;
1721 info_ctr.level = 2;
1722 info_ctr.info.info2 = &info2;
1724 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1725 &info_ctr);
1726 if (W_ERROR_IS_OK(result))
1727 printf ("Printer %s successfully installed.\n", argv[1]);
1729 return result;
1732 /****************************************************************************
1733 ****************************************************************************/
1735 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1736 TALLOC_CTX *mem_ctx,
1737 int argc, const char **argv)
1739 struct policy_handle pol;
1740 WERROR result;
1741 NTSTATUS status;
1742 uint32_t level = 2;
1743 const char *printername;
1744 union spoolss_PrinterInfo info;
1745 struct spoolss_SetPrinterInfoCtr info_ctr;
1746 struct spoolss_SetPrinterInfo2 info2;
1747 struct spoolss_DevmodeContainer devmode_ctr;
1748 struct sec_desc_buf secdesc_ctr;
1750 ZERO_STRUCT(devmode_ctr);
1751 ZERO_STRUCT(secdesc_ctr);
1753 /* parse the command arguments */
1754 if (argc != 3)
1756 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1757 return WERR_OK;
1760 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1762 /* Get a printer handle */
1764 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1765 printername,
1766 PRINTER_ALL_ACCESS,
1767 &pol);
1768 if (!W_ERROR_IS_OK(result))
1769 goto done;
1771 /* Get printer info */
1773 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1774 &pol,
1775 level,
1777 &info);
1778 if (!W_ERROR_IS_OK(result)) {
1779 printf ("Unable to retrieve printer information!\n");
1780 goto done;
1783 /* Set the printer driver */
1785 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1786 info2.drivername = argv[2];
1788 info_ctr.level = 2;
1789 info_ctr.info.info2 = &info2;
1791 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1792 &pol,
1793 &info_ctr,
1794 &devmode_ctr,
1795 &secdesc_ctr,
1796 0, /* command */
1797 &result);
1798 if (!W_ERROR_IS_OK(result)) {
1799 printf("SetPrinter call failed!\n");
1800 goto done;;
1803 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1805 done:
1806 /* Cleanup */
1808 if (is_valid_policy_hnd(&pol))
1809 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1811 return result;
1815 /****************************************************************************
1816 ****************************************************************************/
1818 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1819 TALLOC_CTX *mem_ctx,
1820 int argc, const char **argv)
1822 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1823 NTSTATUS status;
1825 int i;
1826 int vers = -1;
1828 const char *arch = NULL;
1829 uint32_t delete_flags = 0;
1831 /* parse the command arguments */
1832 if (argc < 2 || argc > 4) {
1833 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1834 return WERR_OK;
1837 if (argc >= 3)
1838 arch = argv[2];
1839 if (argc == 4)
1840 vers = atoi (argv[3]);
1842 if (vers >= 0) {
1843 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1846 /* delete the driver for all architectures */
1847 for (i=0; archi_table[i].long_archi; i++) {
1849 if (arch && !strequal( archi_table[i].long_archi, arch))
1850 continue;
1852 if (vers >= 0 && archi_table[i].version != vers)
1853 continue;
1855 /* make the call to remove the driver */
1856 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1857 cli->srv_name_slash,
1858 archi_table[i].long_archi,
1859 argv[1],
1860 delete_flags,
1861 archi_table[i].version,
1862 &result);
1864 if ( !W_ERROR_IS_OK(result) )
1866 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1867 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1868 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1871 else
1873 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1874 archi_table[i].long_archi, archi_table[i].version);
1875 ret = WERR_OK;
1879 return ret;
1883 /****************************************************************************
1884 ****************************************************************************/
1886 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1887 TALLOC_CTX *mem_ctx,
1888 int argc, const char **argv)
1890 WERROR result = WERR_OK;
1891 NTSTATUS status;
1892 int i;
1894 /* parse the command arguments */
1895 if (argc != 2) {
1896 printf ("Usage: %s <driver>\n", argv[0]);
1897 return WERR_OK;
1900 /* delete the driver for all architectures */
1901 for (i=0; archi_table[i].long_archi; i++) {
1902 /* make the call to remove the driver */
1903 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1904 cli->srv_name_slash,
1905 archi_table[i].long_archi,
1906 argv[1],
1907 &result);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 return result;
1911 if ( !W_ERROR_IS_OK(result) ) {
1912 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1913 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1914 argv[1], archi_table[i].long_archi,
1915 W_ERROR_V(result));
1917 } else {
1918 printf ("Driver %s removed for arch [%s].\n", argv[1],
1919 archi_table[i].long_archi);
1923 return result;
1926 /****************************************************************************
1927 ****************************************************************************/
1929 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1930 TALLOC_CTX *mem_ctx,
1931 int argc, const char **argv)
1933 WERROR result;
1934 NTSTATUS status;
1935 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1936 DATA_BLOB buffer;
1937 uint32_t offered;
1938 union spoolss_PrintProcessorDirectoryInfo info;
1939 uint32_t needed;
1941 /* parse the command arguments */
1942 if (argc > 2) {
1943 printf ("Usage: %s [environment]\n", argv[0]);
1944 return WERR_OK;
1947 if (argc == 2) {
1948 environment = argv[1];
1951 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1952 cli->srv_name_slash,
1953 environment,
1955 NULL, /* buffer */
1956 0, /* offered */
1957 NULL, /* info */
1958 &needed,
1959 &result);
1960 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1961 offered = needed;
1962 buffer = data_blob_talloc_zero(mem_ctx, needed);
1964 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1965 cli->srv_name_slash,
1966 environment,
1968 &buffer,
1969 offered,
1970 &info,
1971 &needed,
1972 &result);
1975 if (W_ERROR_IS_OK(result)) {
1976 printf("%s\n", info.info1.directory_name);
1979 return result;
1982 /****************************************************************************
1983 ****************************************************************************/
1985 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1986 int argc, const char **argv)
1988 struct policy_handle handle;
1989 WERROR werror;
1990 NTSTATUS status;
1991 const char *printername;
1992 union spoolss_AddFormInfo info;
1993 struct spoolss_AddFormInfo1 info1;
1994 struct spoolss_AddFormInfo2 info2;
1995 uint32_t level = 1;
1997 /* Parse the command arguments */
1999 if (argc < 3 || argc > 5) {
2000 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2001 return WERR_OK;
2004 /* Get a printer handle */
2006 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2008 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2009 printername,
2010 PRINTER_ALL_ACCESS,
2011 &handle);
2012 if (!W_ERROR_IS_OK(werror))
2013 goto done;
2015 /* Dummy up some values for the form data */
2017 if (argc == 4) {
2018 level = atoi(argv[3]);
2021 switch (level) {
2022 case 1:
2023 info1.flags = SPOOLSS_FORM_USER;
2024 info1.form_name = argv[2];
2025 info1.size.width = 100;
2026 info1.size.height = 100;
2027 info1.area.left = 0;
2028 info1.area.top = 10;
2029 info1.area.right = 20;
2030 info1.area.bottom = 30;
2032 info.info1 = &info1;
2034 break;
2035 case 2:
2036 info2.flags = SPOOLSS_FORM_USER;
2037 info2.form_name = argv[2];
2038 info2.size.width = 100;
2039 info2.size.height = 100;
2040 info2.area.left = 0;
2041 info2.area.top = 10;
2042 info2.area.right = 20;
2043 info2.area.bottom = 30;
2044 info2.keyword = argv[2];
2045 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2046 info2.mui_dll = NULL;
2047 info2.ressource_id = 0;
2048 info2.display_name = argv[2];
2049 info2.lang_id = 0;
2051 info.info2 = &info2;
2053 break;
2056 /* Add the form */
2059 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2060 &handle,
2061 level,
2062 info,
2063 &werror);
2065 done:
2066 if (is_valid_policy_hnd(&handle))
2067 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2069 return werror;
2072 /****************************************************************************
2073 ****************************************************************************/
2075 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2076 int argc, const char **argv)
2078 struct policy_handle handle;
2079 WERROR werror;
2080 NTSTATUS status;
2081 const char *printername;
2082 union spoolss_AddFormInfo info;
2083 struct spoolss_AddFormInfo1 info1;
2085 /* Parse the command arguments */
2087 if (argc != 3) {
2088 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2089 return WERR_OK;
2092 /* Get a printer handle */
2094 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2096 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2097 printername,
2098 SEC_FLAG_MAXIMUM_ALLOWED,
2099 &handle);
2100 if (!W_ERROR_IS_OK(werror))
2101 goto done;
2103 /* Dummy up some values for the form data */
2105 info1.flags = SPOOLSS_FORM_PRINTER;
2106 info1.size.width = 100;
2107 info1.size.height = 100;
2108 info1.area.left = 0;
2109 info1.area.top = 1000;
2110 info1.area.right = 2000;
2111 info1.area.bottom = 3000;
2112 info1.form_name = argv[2];
2114 info.info1 = &info1;
2116 /* Set the form */
2118 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2119 &handle,
2120 argv[2],
2122 info,
2123 &werror);
2125 done:
2126 if (is_valid_policy_hnd(&handle))
2127 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2129 return werror;
2132 /****************************************************************************
2133 ****************************************************************************/
2135 static const char *get_form_flag(int form_flag)
2137 switch (form_flag) {
2138 case SPOOLSS_FORM_USER:
2139 return "FORM_USER";
2140 case SPOOLSS_FORM_BUILTIN:
2141 return "FORM_BUILTIN";
2142 case SPOOLSS_FORM_PRINTER:
2143 return "FORM_PRINTER";
2144 default:
2145 return "unknown";
2149 /****************************************************************************
2150 ****************************************************************************/
2152 static void display_form_info1(struct spoolss_FormInfo1 *r)
2154 printf("%s\n" \
2155 "\tflag: %s (%d)\n" \
2156 "\twidth: %d, length: %d\n" \
2157 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2158 r->form_name, get_form_flag(r->flags), r->flags,
2159 r->size.width, r->size.height,
2160 r->area.left, r->area.right,
2161 r->area.top, r->area.bottom);
2164 /****************************************************************************
2165 ****************************************************************************/
2167 static void display_form_info2(struct spoolss_FormInfo2 *r)
2169 printf("%s\n" \
2170 "\tflag: %s (%d)\n" \
2171 "\twidth: %d, length: %d\n" \
2172 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2173 r->form_name, get_form_flag(r->flags), r->flags,
2174 r->size.width, r->size.height,
2175 r->area.left, r->area.right,
2176 r->area.top, r->area.bottom);
2177 printf("\tkeyword: %s\n", r->keyword);
2178 printf("\tstring_type: 0x%08x\n", r->string_type);
2179 printf("\tmui_dll: %s\n", r->mui_dll);
2180 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2181 printf("\tdisplay_name: %s\n", r->display_name);
2182 printf("\tlang_id: %d\n", r->lang_id);
2183 printf("\n");
2186 /****************************************************************************
2187 ****************************************************************************/
2189 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2190 int argc, const char **argv)
2192 struct policy_handle handle;
2193 WERROR werror;
2194 NTSTATUS status;
2195 const char *printername;
2196 DATA_BLOB buffer;
2197 uint32_t offered = 0;
2198 union spoolss_FormInfo info;
2199 uint32_t needed;
2200 uint32_t level = 1;
2202 /* Parse the command arguments */
2204 if (argc < 3 || argc > 5) {
2205 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2206 return WERR_OK;
2209 /* Get a printer handle */
2211 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2213 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2214 printername,
2215 SEC_FLAG_MAXIMUM_ALLOWED,
2216 &handle);
2217 if (!W_ERROR_IS_OK(werror))
2218 goto done;
2220 if (argc == 4) {
2221 level = atoi(argv[3]);
2224 /* Get the form */
2226 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2227 &handle,
2228 argv[2],
2229 level,
2230 NULL,
2231 offered,
2232 &info,
2233 &needed,
2234 &werror);
2235 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2236 buffer = data_blob_talloc_zero(mem_ctx, needed);
2237 offered = needed;
2238 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2239 &handle,
2240 argv[2],
2241 level,
2242 &buffer,
2243 offered,
2244 &info,
2245 &needed,
2246 &werror);
2249 if (!NT_STATUS_IS_OK(status)) {
2250 return werror;
2253 switch (level) {
2254 case 1:
2255 display_form_info1(&info.info1);
2256 break;
2257 case 2:
2258 display_form_info2(&info.info2);
2259 break;
2262 done:
2263 if (is_valid_policy_hnd(&handle))
2264 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2266 return werror;
2269 /****************************************************************************
2270 ****************************************************************************/
2272 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2273 TALLOC_CTX *mem_ctx, int argc,
2274 const char **argv)
2276 struct policy_handle handle;
2277 WERROR werror;
2278 NTSTATUS status;
2279 const char *printername;
2281 /* Parse the command arguments */
2283 if (argc != 3) {
2284 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2285 return WERR_OK;
2288 /* Get a printer handle */
2290 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2292 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2293 printername,
2294 SEC_FLAG_MAXIMUM_ALLOWED,
2295 &handle);
2296 if (!W_ERROR_IS_OK(werror))
2297 goto done;
2299 /* Delete the form */
2301 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2302 &handle,
2303 argv[2],
2304 &werror);
2305 if (!NT_STATUS_IS_OK(status)) {
2306 return ntstatus_to_werror(status);
2309 done:
2310 if (is_valid_policy_hnd(&handle))
2311 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2313 return werror;
2316 /****************************************************************************
2317 ****************************************************************************/
2319 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2320 TALLOC_CTX *mem_ctx, int argc,
2321 const char **argv)
2323 struct policy_handle handle;
2324 WERROR werror;
2325 const char *printername;
2326 uint32_t num_forms, level = 1, i;
2327 union spoolss_FormInfo *forms;
2329 /* Parse the command arguments */
2331 if (argc < 2 || argc > 4) {
2332 printf ("Usage: %s <printer> [level]\n", argv[0]);
2333 return WERR_OK;
2336 /* Get a printer handle */
2338 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2340 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2341 printername,
2342 SEC_FLAG_MAXIMUM_ALLOWED,
2343 &handle);
2344 if (!W_ERROR_IS_OK(werror))
2345 goto done;
2347 if (argc == 3) {
2348 level = atoi(argv[2]);
2351 /* Enumerate forms */
2353 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2354 &handle,
2355 level,
2357 &num_forms,
2358 &forms);
2360 if (!W_ERROR_IS_OK(werror))
2361 goto done;
2363 /* Display output */
2365 for (i = 0; i < num_forms; i++) {
2366 switch (level) {
2367 case 1:
2368 display_form_info1(&forms[i].info1);
2369 break;
2370 case 2:
2371 display_form_info2(&forms[i].info2);
2372 break;
2376 done:
2377 if (is_valid_policy_hnd(&handle))
2378 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2380 return werror;
2383 /****************************************************************************
2384 ****************************************************************************/
2386 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2387 TALLOC_CTX *mem_ctx,
2388 int argc, const char **argv)
2390 WERROR result;
2391 NTSTATUS status;
2392 const char *printername;
2393 struct policy_handle pol;
2394 union spoolss_PrinterInfo info;
2395 enum winreg_Type type;
2396 union spoolss_PrinterData data;
2397 DATA_BLOB blob;
2399 /* parse the command arguments */
2400 if (argc < 5) {
2401 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2402 " <value> <data>\n",
2403 argv[0]);
2404 return WERR_OK;
2407 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2409 type = REG_NONE;
2411 if (strequal(argv[2], "string")) {
2412 type = REG_SZ;
2415 if (strequal(argv[2], "binary")) {
2416 type = REG_BINARY;
2419 if (strequal(argv[2], "dword")) {
2420 type = REG_DWORD;
2423 if (strequal(argv[2], "multistring")) {
2424 type = REG_MULTI_SZ;
2427 if (type == REG_NONE) {
2428 printf("Unknown data type: %s\n", argv[2]);
2429 result = WERR_INVALID_PARAM;
2430 goto done;
2433 /* get a printer handle */
2435 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2436 printername,
2437 SEC_FLAG_MAXIMUM_ALLOWED,
2438 &pol);
2439 if (!W_ERROR_IS_OK(result)) {
2440 goto done;
2443 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2444 &pol,
2447 &info);
2448 if (!W_ERROR_IS_OK(result)) {
2449 goto done;
2452 printf("%s\n", current_timestring(mem_ctx, true));
2453 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2455 /* Set the printer data */
2457 switch (type) {
2458 case REG_SZ:
2459 data.string = talloc_strdup(mem_ctx, argv[4]);
2460 W_ERROR_HAVE_NO_MEMORY(data.string);
2461 break;
2462 case REG_DWORD:
2463 data.value = strtoul(argv[4], NULL, 10);
2464 break;
2465 case REG_BINARY:
2466 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2467 break;
2468 case REG_MULTI_SZ: {
2469 int i, num_strings;
2470 const char **strings = NULL;
2472 for (i=4; i<argc; i++) {
2473 if (strcmp(argv[i], "NULL") == 0) {
2474 argv[i] = "";
2476 if (!add_string_to_array(mem_ctx, argv[i],
2477 &strings,
2478 &num_strings)) {
2479 result = WERR_NOMEM;
2480 goto done;
2483 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2484 if (!data.string_array) {
2485 result = WERR_NOMEM;
2486 goto done;
2488 for (i=0; i < num_strings; i++) {
2489 data.string_array[i] = strings[i];
2491 break;
2493 default:
2494 printf("Unknown data type: %s\n", argv[2]);
2495 result = WERR_INVALID_PARAM;
2496 goto done;
2499 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2500 if (!W_ERROR_IS_OK(result)) {
2501 goto done;
2504 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2505 &pol,
2506 argv[3], /* value_name */
2507 type,
2508 blob.data,
2509 blob.length,
2510 &result);
2511 if (!W_ERROR_IS_OK(result)) {
2512 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2513 goto done;
2515 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2517 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2518 &pol,
2521 &info);
2522 if (!W_ERROR_IS_OK(result)) {
2523 goto done;
2526 printf("%s\n", current_timestring(mem_ctx, true));
2527 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2529 done:
2530 /* cleanup */
2531 if (is_valid_policy_hnd(&pol)) {
2532 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2535 return result;
2538 /****************************************************************************
2539 ****************************************************************************/
2541 static void display_job_info1(struct spoolss_JobInfo1 *r)
2543 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2544 r->user_name, r->document_name, r->text_status, r->pages_printed,
2545 r->total_pages);
2548 /****************************************************************************
2549 ****************************************************************************/
2551 static void display_job_info2(struct spoolss_JobInfo2 *r)
2553 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2554 r->position, r->job_id,
2555 r->user_name, r->document_name, r->text_status, r->pages_printed,
2556 r->total_pages, r->size);
2559 /****************************************************************************
2560 ****************************************************************************/
2562 static void display_job_info3(struct spoolss_JobInfo3 *r)
2564 printf("jobid[%d], next_jobid[%d]\n",
2565 r->job_id, r->next_job_id);
2568 /****************************************************************************
2569 ****************************************************************************/
2571 static void display_job_info4(struct spoolss_JobInfo4 *r)
2573 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2574 r->position, r->job_id,
2575 r->user_name, r->document_name, r->text_status, r->pages_printed,
2576 r->total_pages, r->size, r->size_high);
2579 /****************************************************************************
2580 ****************************************************************************/
2582 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2583 TALLOC_CTX *mem_ctx, int argc,
2584 const char **argv)
2586 WERROR result;
2587 uint32_t level = 1, count, i;
2588 const char *printername;
2589 struct policy_handle hnd;
2590 union spoolss_JobInfo *info;
2592 if (argc < 2 || argc > 3) {
2593 printf("Usage: %s printername [level]\n", argv[0]);
2594 return WERR_OK;
2597 if (argc == 3) {
2598 level = atoi(argv[2]);
2601 /* Open printer handle */
2603 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2605 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2606 printername,
2607 SEC_FLAG_MAXIMUM_ALLOWED,
2608 &hnd);
2609 if (!W_ERROR_IS_OK(result))
2610 goto done;
2612 /* Enumerate ports */
2614 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2615 &hnd,
2616 0, /* firstjob */
2617 1000, /* numjobs */
2618 level,
2620 &count,
2621 &info);
2622 if (!W_ERROR_IS_OK(result)) {
2623 goto done;
2626 for (i = 0; i < count; i++) {
2627 switch (level) {
2628 case 1:
2629 display_job_info1(&info[i].info1);
2630 break;
2631 case 2:
2632 display_job_info2(&info[i].info2);
2633 break;
2634 default:
2635 d_printf("unknown info level %d\n", level);
2636 break;
2640 done:
2641 if (is_valid_policy_hnd(&hnd)) {
2642 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2645 return result;
2648 /****************************************************************************
2649 ****************************************************************************/
2651 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2652 TALLOC_CTX *mem_ctx, int argc,
2653 const char **argv)
2655 WERROR result;
2656 const char *printername;
2657 struct policy_handle hnd;
2658 uint32_t job_id;
2659 uint32_t level = 1;
2660 union spoolss_JobInfo info;
2662 if (argc < 3 || argc > 4) {
2663 printf("Usage: %s printername job_id [level]\n", argv[0]);
2664 return WERR_OK;
2667 job_id = atoi(argv[2]);
2669 if (argc == 4) {
2670 level = atoi(argv[3]);
2673 /* Open printer handle */
2675 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2677 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2678 printername,
2679 SEC_FLAG_MAXIMUM_ALLOWED,
2680 &hnd);
2681 if (!W_ERROR_IS_OK(result)) {
2682 goto done;
2685 /* Enumerate ports */
2687 result = rpccli_spoolss_getjob(cli, mem_ctx,
2688 &hnd,
2689 job_id,
2690 level,
2692 &info);
2694 if (!W_ERROR_IS_OK(result)) {
2695 goto done;
2698 switch (level) {
2699 case 1:
2700 display_job_info1(&info.info1);
2701 break;
2702 case 2:
2703 display_job_info2(&info.info2);
2704 break;
2705 case 3:
2706 display_job_info3(&info.info3);
2707 break;
2708 case 4:
2709 display_job_info4(&info.info4);
2710 break;
2711 default:
2712 d_printf("unknown info level %d\n", level);
2713 break;
2716 done:
2717 if (is_valid_policy_hnd(&hnd)) {
2718 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2721 return result;
2724 /****************************************************************************
2725 ****************************************************************************/
2727 static struct {
2728 const char *name;
2729 enum spoolss_JobControl val;
2730 } cmdvals[] = {
2731 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2732 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2733 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2734 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2735 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2736 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2737 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2738 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2739 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2742 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2744 int i;
2746 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2747 if (strequal(cmdvals[i].name, cmd)) {
2748 return cmdvals[i].val;
2751 return (enum spoolss_JobControl)atoi(cmd);
2754 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2755 TALLOC_CTX *mem_ctx, int argc,
2756 const char **argv)
2758 WERROR result;
2759 NTSTATUS status;
2760 const char *printername;
2761 struct policy_handle hnd;
2762 uint32_t job_id;
2763 enum spoolss_JobControl command;
2765 if (argc != 4) {
2766 printf("Usage: %s printername job_id command\n", argv[0]);
2767 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2768 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2769 return WERR_OK;
2772 job_id = atoi(argv[2]);
2773 command = parse_setjob_command(argv[3]);
2775 /* Open printer handle */
2777 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2779 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2780 printername,
2781 SEC_FLAG_MAXIMUM_ALLOWED,
2782 &hnd);
2783 if (!W_ERROR_IS_OK(result)) {
2784 goto done;
2787 /* Set Job */
2789 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2790 &hnd,
2791 job_id,
2792 NULL,
2793 command,
2794 &result);
2796 if (!W_ERROR_IS_OK(result)) {
2797 goto done;
2800 done:
2801 if (is_valid_policy_hnd(&hnd)) {
2802 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2805 return result;
2808 /****************************************************************************
2809 ****************************************************************************/
2811 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2812 TALLOC_CTX *mem_ctx, int argc,
2813 const char **argv)
2815 WERROR result;
2816 NTSTATUS status;
2817 uint32_t i = 0;
2818 const char *printername;
2819 struct policy_handle hnd;
2820 uint32_t value_offered = 0;
2821 const char *value_name = NULL;
2822 uint32_t value_needed;
2823 enum winreg_Type type;
2824 uint8_t *data = NULL;
2825 uint32_t data_offered = 0;
2826 uint32_t data_needed;
2828 if (argc != 2) {
2829 printf("Usage: %s printername\n", argv[0]);
2830 return WERR_OK;
2833 /* Open printer handle */
2835 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2837 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2838 printername,
2839 SEC_FLAG_MAXIMUM_ALLOWED,
2840 &hnd);
2841 if (!W_ERROR_IS_OK(result)) {
2842 goto done;
2845 /* Enumerate data */
2847 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2848 &hnd,
2850 value_name,
2851 value_offered,
2852 &value_needed,
2853 &type,
2854 data,
2855 data_offered,
2856 &data_needed,
2857 &result);
2859 data_offered = data_needed;
2860 value_offered = value_needed;
2861 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2862 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2864 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2866 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2867 &hnd,
2868 i++,
2869 value_name,
2870 value_offered,
2871 &value_needed,
2872 &type,
2873 data,
2874 data_offered,
2875 &data_needed,
2876 &result);
2877 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2878 struct regval_blob *v;
2880 v = regval_compose(talloc_tos(),
2881 value_name,
2882 type,
2883 data,
2884 data_offered);
2885 if (v == NULL) {
2886 result = WERR_NOMEM;
2887 goto done;
2890 display_reg_value(v);
2891 talloc_free(v);
2895 if (W_ERROR_V(result) == ERRnomoreitems) {
2896 result = W_ERROR(ERRsuccess);
2899 done:
2900 if (is_valid_policy_hnd(&hnd)) {
2901 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2904 return result;
2907 /****************************************************************************
2908 ****************************************************************************/
2910 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2911 TALLOC_CTX *mem_ctx, int argc,
2912 const char **argv)
2914 WERROR result;
2915 uint32_t i;
2916 const char *printername;
2917 struct policy_handle hnd;
2918 uint32_t count;
2919 struct spoolss_PrinterEnumValues *info;
2921 if (argc != 3) {
2922 printf("Usage: %s printername <keyname>\n", argv[0]);
2923 return WERR_OK;
2926 /* Open printer handle */
2928 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2930 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2931 printername,
2932 SEC_FLAG_MAXIMUM_ALLOWED,
2933 &hnd);
2934 if (!W_ERROR_IS_OK(result)) {
2935 goto done;
2938 /* Enumerate subkeys */
2940 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2941 &hnd,
2942 argv[2],
2944 &count,
2945 &info);
2946 if (!W_ERROR_IS_OK(result)) {
2947 goto done;
2950 for (i=0; i < count; i++) {
2951 display_printer_data(info[i].value_name,
2952 info[i].type,
2953 info[i].data->data,
2954 info[i].data->length);
2957 done:
2958 if (is_valid_policy_hnd(&hnd)) {
2959 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2962 return result;
2965 /****************************************************************************
2966 ****************************************************************************/
2968 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2969 TALLOC_CTX *mem_ctx, int argc,
2970 const char **argv)
2972 WERROR result;
2973 const char *printername;
2974 const char *keyname = NULL;
2975 struct policy_handle hnd;
2976 const char **key_buffer = NULL;
2977 int i;
2978 uint32_t offered = 0;
2980 if (argc < 2 || argc > 4) {
2981 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
2982 return WERR_OK;
2985 if (argc >= 3) {
2986 keyname = argv[2];
2987 } else {
2988 keyname = "";
2991 if (argc == 4) {
2992 offered = atoi(argv[3]);
2995 /* Open printer handle */
2997 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2999 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3000 printername,
3001 SEC_FLAG_MAXIMUM_ALLOWED,
3002 &hnd);
3003 if (!W_ERROR_IS_OK(result)) {
3004 goto done;
3007 /* Enumerate subkeys */
3009 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3010 &hnd,
3011 keyname,
3012 &key_buffer,
3013 offered);
3015 if (!W_ERROR_IS_OK(result)) {
3016 goto done;
3019 for (i=0; key_buffer && key_buffer[i]; i++) {
3020 printf("%s\n", key_buffer[i]);
3023 done:
3025 if (is_valid_policy_hnd(&hnd)) {
3026 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3029 return result;
3032 /****************************************************************************
3033 ****************************************************************************/
3035 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3036 TALLOC_CTX *mem_ctx, int argc,
3037 const char **argv)
3039 const char *printername;
3040 const char *clientname;
3041 struct policy_handle hnd;
3042 WERROR result;
3043 NTSTATUS status;
3044 struct spoolss_NotifyOption option;
3046 if (argc != 2) {
3047 printf("Usage: %s printername\n", argv[0]);
3048 result = WERR_OK;
3049 goto done;
3052 /* Open printer */
3054 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3056 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3057 printername,
3058 SEC_FLAG_MAXIMUM_ALLOWED,
3059 &hnd);
3060 if (!W_ERROR_IS_OK(result)) {
3061 printf("Error opening %s\n", argv[1]);
3062 goto done;
3065 /* Create spool options */
3067 option.version = 2;
3068 option.count = 2;
3070 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3071 if (option.types == NULL) {
3072 result = WERR_NOMEM;
3073 goto done;
3076 option.types[0].type = PRINTER_NOTIFY_TYPE;
3077 option.types[0].count = 1;
3078 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3079 if (option.types[0].fields == NULL) {
3080 result = WERR_NOMEM;
3081 goto done;
3083 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3085 option.types[1].type = JOB_NOTIFY_TYPE;
3086 option.types[1].count = 1;
3087 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3088 if (option.types[1].fields == NULL) {
3089 result = WERR_NOMEM;
3090 goto done;
3092 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3094 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3095 if (!clientname) {
3096 result = WERR_NOMEM;
3097 goto done;
3100 /* Send rffpcnex */
3102 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3103 &hnd,
3106 clientname,
3107 123,
3108 &option,
3109 &result);
3110 if (!W_ERROR_IS_OK(result)) {
3111 printf("Error rffpcnex %s\n", argv[1]);
3112 goto done;
3115 done:
3116 if (is_valid_policy_hnd(&hnd))
3117 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3119 return result;
3122 /****************************************************************************
3123 ****************************************************************************/
3125 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3126 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3128 union spoolss_PrinterInfo info1, info2;
3129 WERROR werror;
3130 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3132 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3133 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3134 hnd1,
3137 &info1);
3138 if ( !W_ERROR_IS_OK(werror) ) {
3139 printf("failed (%s)\n", win_errstr(werror));
3140 talloc_destroy(mem_ctx);
3141 return false;
3143 printf("ok\n");
3145 printf("Retrieving printer properties for %s...", cli2->desthost);
3146 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3147 hnd2,
3150 &info2);
3151 if ( !W_ERROR_IS_OK(werror) ) {
3152 printf("failed (%s)\n", win_errstr(werror));
3153 talloc_destroy(mem_ctx);
3154 return false;
3156 printf("ok\n");
3158 talloc_destroy(mem_ctx);
3160 return true;
3163 /****************************************************************************
3164 ****************************************************************************/
3166 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3167 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3169 union spoolss_PrinterInfo info1, info2;
3170 WERROR werror;
3171 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3172 struct security_descriptor *sd1, *sd2;
3173 bool result = true;
3176 printf("Retrieving printer security for %s...", cli1->desthost);
3177 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3178 hnd1,
3181 &info1);
3182 if ( !W_ERROR_IS_OK(werror) ) {
3183 printf("failed (%s)\n", win_errstr(werror));
3184 result = false;
3185 goto done;
3187 printf("ok\n");
3189 printf("Retrieving printer security for %s...", cli2->desthost);
3190 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3191 hnd2,
3194 &info2);
3195 if ( !W_ERROR_IS_OK(werror) ) {
3196 printf("failed (%s)\n", win_errstr(werror));
3197 result = false;
3198 goto done;
3200 printf("ok\n");
3203 printf("++ ");
3205 sd1 = info1.info3.secdesc;
3206 sd2 = info2.info3.secdesc;
3208 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3209 printf("NULL secdesc!\n");
3210 result = false;
3211 goto done;
3214 if (!security_descriptor_equal( sd1, sd2 ) ) {
3215 printf("Security Descriptors *not* equal!\n");
3216 result = false;
3217 goto done;
3220 printf("Security descriptors match\n");
3222 done:
3223 talloc_destroy(mem_ctx);
3224 return result;
3228 /****************************************************************************
3229 ****************************************************************************/
3231 extern struct user_auth_info *rpcclient_auth_info;
3233 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3234 TALLOC_CTX *mem_ctx, int argc,
3235 const char **argv)
3237 const char *printername;
3238 char *printername_path = NULL;
3239 struct cli_state *cli_server2 = NULL;
3240 struct rpc_pipe_client *cli2 = NULL;
3241 struct policy_handle hPrinter1, hPrinter2;
3242 NTSTATUS nt_status;
3243 WERROR werror;
3245 if ( argc != 3 ) {
3246 printf("Usage: %s <printer> <server>\n", argv[0]);
3247 return WERR_OK;
3250 printername = argv[1];
3252 /* first get the connection to the remote server */
3254 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3255 NULL, 0,
3256 "IPC$", "IPC",
3257 get_cmdline_auth_info_username(rpcclient_auth_info),
3258 lp_workgroup(),
3259 get_cmdline_auth_info_password(rpcclient_auth_info),
3260 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3261 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3263 if ( !NT_STATUS_IS_OK(nt_status) )
3264 return WERR_GENERAL_FAILURE;
3266 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3267 &cli2);
3268 if (!NT_STATUS_IS_OK(nt_status)) {
3269 printf("failed to open spoolss pipe on server %s (%s)\n",
3270 argv[2], nt_errstr(nt_status));
3271 return WERR_GENERAL_FAILURE;
3274 /* now open up both printers */
3276 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3278 printf("Opening %s...", printername_path);
3280 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3281 printername_path,
3282 PRINTER_ALL_ACCESS,
3283 &hPrinter1);
3284 if ( !W_ERROR_IS_OK(werror) ) {
3285 printf("failed (%s)\n", win_errstr(werror));
3286 goto done;
3288 printf("ok\n");
3290 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3292 printf("Opening %s...", printername_path);
3293 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3294 printername_path,
3295 PRINTER_ALL_ACCESS,
3296 &hPrinter2);
3297 if ( !W_ERROR_IS_OK(werror) ) {
3298 printf("failed (%s)\n", win_errstr(werror));
3299 goto done;
3301 printf("ok\n");
3303 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3304 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3305 #if 0
3306 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3307 #endif
3310 done:
3311 /* cleanup */
3313 printf("Closing printers...");
3314 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3315 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3316 printf("ok\n");
3318 /* close the second remote connection */
3320 cli_shutdown( cli_server2 );
3321 return WERR_OK;
3324 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3326 printf("print_processor_name: %s\n", r->print_processor_name);
3329 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3330 TALLOC_CTX *mem_ctx, int argc,
3331 const char **argv)
3333 WERROR werror;
3334 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3335 uint32_t num_procs, level = 1, i;
3336 union spoolss_PrintProcessorInfo *procs;
3338 /* Parse the command arguments */
3340 if (argc < 1 || argc > 4) {
3341 printf ("Usage: %s [environment] [level]\n", argv[0]);
3342 return WERR_OK;
3345 if (argc >= 2) {
3346 environment = argv[1];
3349 if (argc == 3) {
3350 level = atoi(argv[2]);
3353 /* Enumerate Print Processors */
3355 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3356 cli->srv_name_slash,
3357 environment,
3358 level,
3360 &num_procs,
3361 &procs);
3362 if (!W_ERROR_IS_OK(werror))
3363 goto done;
3365 /* Display output */
3367 for (i = 0; i < num_procs; i++) {
3368 switch (level) {
3369 case 1:
3370 display_proc_info1(&procs[i].info1);
3371 break;
3375 done:
3376 return werror;
3379 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3381 printf("name_array: %s\n", r->name_array);
3384 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3385 TALLOC_CTX *mem_ctx, int argc,
3386 const char **argv)
3388 WERROR werror;
3389 const char *print_processor_name = "winprint";
3390 uint32_t num_procs, level = 1, i;
3391 union spoolss_PrintProcDataTypesInfo *procs;
3393 /* Parse the command arguments */
3395 if (argc < 1 || argc > 4) {
3396 printf ("Usage: %s [environment] [level]\n", argv[0]);
3397 return WERR_OK;
3400 if (argc >= 2) {
3401 print_processor_name = argv[1];
3404 if (argc == 3) {
3405 level = atoi(argv[2]);
3408 /* Enumerate Print Processor Data Types */
3410 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3411 cli->srv_name_slash,
3412 print_processor_name,
3413 level,
3415 &num_procs,
3416 &procs);
3417 if (!W_ERROR_IS_OK(werror))
3418 goto done;
3420 /* Display output */
3422 for (i = 0; i < num_procs; i++) {
3423 switch (level) {
3424 case 1:
3425 display_proc_data_types_info1(&procs[i].info1);
3426 break;
3430 done:
3431 return werror;
3434 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3436 printf("monitor_name: %s\n", r->monitor_name);
3439 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3441 printf("monitor_name: %s\n", r->monitor_name);
3442 printf("environment: %s\n", r->environment);
3443 printf("dll_name: %s\n", r->dll_name);
3446 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3447 TALLOC_CTX *mem_ctx, int argc,
3448 const char **argv)
3450 WERROR werror;
3451 uint32_t count, level = 1, i;
3452 union spoolss_MonitorInfo *info;
3454 /* Parse the command arguments */
3456 if (argc > 2) {
3457 printf("Usage: %s [level]\n", argv[0]);
3458 return WERR_OK;
3461 if (argc == 2) {
3462 level = atoi(argv[1]);
3465 /* Enumerate Print Monitors */
3467 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3468 cli->srv_name_slash,
3469 level,
3471 &count,
3472 &info);
3473 if (!W_ERROR_IS_OK(werror)) {
3474 goto done;
3477 /* Display output */
3479 for (i = 0; i < count; i++) {
3480 switch (level) {
3481 case 1:
3482 display_monitor1(&info[i].info1);
3483 break;
3484 case 2:
3485 display_monitor2(&info[i].info2);
3486 break;
3490 done:
3491 return werror;
3494 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3495 TALLOC_CTX *mem_ctx, int argc,
3496 const char **argv)
3498 WERROR result;
3499 NTSTATUS status;
3500 struct policy_handle handle, gdi_handle;
3501 const char *printername;
3502 struct spoolss_DevmodeContainer devmode_ctr;
3504 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3506 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3507 printername,
3508 SEC_FLAG_MAXIMUM_ALLOWED,
3509 &handle);
3510 if (!W_ERROR_IS_OK(result)) {
3511 return result;
3514 ZERO_STRUCT(devmode_ctr);
3516 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3517 &handle,
3518 &gdi_handle,
3519 &devmode_ctr,
3520 &result);
3521 if (!W_ERROR_IS_OK(result)) {
3522 goto done;
3525 done:
3526 if (is_valid_policy_hnd(&gdi_handle)) {
3527 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3529 if (is_valid_policy_hnd(&handle)) {
3530 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3533 return result;
3536 /* List of commands exported by this module */
3537 struct cmd_set spoolss_commands[] = {
3539 { "SPOOLSS" },
3541 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3542 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3543 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3544 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3545 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3546 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3547 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3548 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3549 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3550 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3551 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3552 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3553 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3554 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3555 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3556 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3557 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3558 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3559 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3560 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3561 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3562 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3563 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3564 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3565 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3566 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3567 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3568 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3569 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3570 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3571 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3572 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3573 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3574 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3575 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3577 { NULL }