s3-rpcclient: add delpermachineconnection command
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blob700813eaa9e6a599f4c1bad388df271ee5e74e47
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/ndr_spoolss_c.h"
28 #include "../librpc/gen_ndr/ndr_spoolss.h"
29 #include "rpc_client/cli_spoolss.h"
30 #include "rpc_client/init_spoolss.h"
31 #include "nt_printing.h"
32 #include "../libcli/security/display_sec.h"
33 #include "../libcli/security/security_descriptor.h"
34 #include "../libcli/registry/util_reg.h"
35 #include "libsmb/libsmb.h"
36 #include "popt_common_cmdline.h"
38 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
39 { \
40 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
41 _cli->srv_name_slash, _arg); \
42 W_ERROR_HAVE_NO_MEMORY(_printername); \
45 /* The version int is used by getdrivers. Note that
46 all architecture strings that support mutliple
47 versions must be grouped together since enumdrivers
48 uses this property to prevent issuing multiple
49 enumdriver calls for the same arch */
52 static const struct print_architecture_table_node archi_table[]= {
54 {"Windows 4.0", "WIN40", 0 },
55 {"Windows NT x86", "W32X86", 2 },
56 {"Windows NT x86", "W32X86", 3 },
57 {"Windows NT R4000", "W32MIPS", 2 },
58 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
59 {"Windows NT PowerPC", "W32PPC", 2 },
60 {"Windows IA64", "IA64", 3 },
61 {"Windows x64", "x64", 3 },
62 {NULL, "", -1 }
65 /**
66 * @file
68 * rpcclient module for SPOOLSS rpc pipe.
70 * This generally just parses and checks command lines, and then calls
71 * a cli_spoolss function.
72 **/
74 /****************************************************************************
75 function to do the mapping between the long architecture name and
76 the short one.
77 ****************************************************************************/
79 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
81 int i=-1;
83 DEBUG(107,("Getting architecture dependent directory\n"));
84 do {
85 i++;
86 } while ( (archi_table[i].long_archi!=NULL ) &&
87 strcasecmp_m(long_archi, archi_table[i].long_archi) );
89 if (archi_table[i].long_archi==NULL) {
90 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
91 return NULL;
94 /* this might be client code - but shouldn't this be an fstrcpy etc? */
97 DEBUGADD(108,("index: [%d]\n", i));
98 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
99 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
101 return archi_table[i].short_archi;
104 /****************************************************************************
105 ****************************************************************************/
107 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
108 TALLOC_CTX *mem_ctx,
109 int argc, const char **argv)
111 WERROR werror;
112 struct policy_handle hnd;
113 uint32_t access_mask = PRINTER_ALL_ACCESS;
114 struct dcerpc_binding_handle *b = cli->binding_handle;
116 if (argc < 2) {
117 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
118 return WERR_OK;
121 if (argc >= 3) {
122 sscanf(argv[2], "%x", &access_mask);
125 /* Open the printer handle */
127 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
128 argv[1],
129 access_mask,
130 &hnd);
131 if (W_ERROR_IS_OK(werror)) {
132 printf("Printer %s opened successfully\n", argv[1]);
133 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
135 if (!W_ERROR_IS_OK(werror)) {
136 printf("Error closing printer handle! (%s)\n",
137 get_dos_error_msg(werror));
141 return werror;
144 /****************************************************************************
145 ****************************************************************************/
147 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
148 TALLOC_CTX *mem_ctx,
149 int argc, const char **argv)
151 WERROR werror;
152 struct policy_handle hnd;
153 uint32_t access_mask = PRINTER_ALL_ACCESS;
154 NTSTATUS status;
155 struct spoolss_DevmodeContainer devmode_ctr;
156 struct dcerpc_binding_handle *b = cli->binding_handle;
158 ZERO_STRUCT(devmode_ctr);
160 if (argc < 2) {
161 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
162 return WERR_OK;
165 if (argc >= 3) {
166 sscanf(argv[2], "%x", &access_mask);
169 /* Open the printer handle */
171 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
172 argv[1],
173 NULL,
174 devmode_ctr,
175 access_mask,
176 &hnd,
177 &werror);
178 if (!NT_STATUS_IS_OK(status)) {
179 return ntstatus_to_werror(status);
181 if (W_ERROR_IS_OK(werror)) {
182 printf("Printer %s opened successfully\n", argv[1]);
183 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
185 if (!W_ERROR_IS_OK(werror)) {
186 printf("Error closing printer handle! (%s)\n",
187 get_dos_error_msg(werror));
191 return werror;
194 /****************************************************************************
195 ****************************************************************************/
197 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
199 if (!r)
200 return;
202 printf("\tprintername:[%s]\n", r->printername);
203 printf("\tservername:[%s]\n", r->servername);
204 printf("\tcjobs:[0x%x]\n", r->cjobs);
205 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
206 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
207 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
208 r->time.day, r->time.day_of_week);
209 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
210 r->time.second, r->time.millisecond);
212 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
213 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
215 printf("\tversion:[0x%x]\n", r->version);
216 printf("\tfree_build:[0x%x]\n", r->free_build);
217 printf("\tspooling:[0x%x]\n", r->spooling);
218 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
219 printf("\tsession_counter:[0x%x]\n", r->session_counter);
220 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
221 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
222 printf("\tjob_error:[0x%x]\n", r->job_error);
223 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
224 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
225 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
226 printf("\tchange_id:[0x%x]\n", r->change_id);
227 printf("\tlast_error: %s\n", win_errstr(r->last_error));
228 printf("\tstatus:[0x%x]\n", r->status);
229 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
230 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
231 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
232 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
233 printf("\tref_ic:[0x%x]\n", r->ref_ic);
234 printf("\treserved2:[0x%x]\n", r->reserved2);
235 printf("\treserved3:[0x%x]\n", r->reserved3);
237 printf("\n");
240 /****************************************************************************
241 ****************************************************************************/
243 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
245 printf("\tflags:[0x%x]\n", r->flags);
246 printf("\tname:[%s]\n", r->name);
247 printf("\tdescription:[%s]\n", r->description);
248 printf("\tcomment:[%s]\n", r->comment);
250 printf("\n");
253 /****************************************************************************
254 ****************************************************************************/
256 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
258 printf("\tservername:[%s]\n", r->servername);
259 printf("\tprintername:[%s]\n", r->printername);
260 printf("\tsharename:[%s]\n", r->sharename);
261 printf("\tportname:[%s]\n", r->portname);
262 printf("\tdrivername:[%s]\n", r->drivername);
263 printf("\tcomment:[%s]\n", r->comment);
264 printf("\tlocation:[%s]\n", r->location);
265 printf("\tsepfile:[%s]\n", r->sepfile);
266 printf("\tprintprocessor:[%s]\n", r->printprocessor);
267 printf("\tdatatype:[%s]\n", r->datatype);
268 printf("\tparameters:[%s]\n", r->parameters);
269 printf("\tattributes:[0x%x]\n", r->attributes);
270 printf("\tpriority:[0x%x]\n", r->priority);
271 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
272 printf("\tstarttime:[0x%x]\n", r->starttime);
273 printf("\tuntiltime:[0x%x]\n", r->untiltime);
274 printf("\tstatus:[0x%x]\n", r->status);
275 printf("\tcjobs:[0x%x]\n", r->cjobs);
276 printf("\taverageppm:[0x%x]\n", r->averageppm);
278 if (r->secdesc)
279 display_sec_desc(r->secdesc);
281 printf("\n");
284 /****************************************************************************
285 ****************************************************************************/
287 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
289 display_sec_desc(r->secdesc);
291 printf("\n");
294 /****************************************************************************
295 ****************************************************************************/
297 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
299 printf("\tservername:[%s]\n", r->servername);
300 printf("\tprintername:[%s]\n", r->printername);
301 printf("\tattributes:[0x%x]\n", r->attributes);
302 printf("\n");
305 /****************************************************************************
306 ****************************************************************************/
308 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
310 printf("\tprintername:[%s]\n", r->printername);
311 printf("\tportname:[%s]\n", r->portname);
312 printf("\tattributes:[0x%x]\n", r->attributes);
313 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
314 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
315 printf("\n");
318 /****************************************************************************
319 ****************************************************************************/
321 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
323 printf("\tstatus:[0x%x]\n", r->status);
324 printf("\n");
327 /****************************************************************************
328 ****************************************************************************/
330 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
332 printf("\tguid:[%s]\n", r->guid);
333 printf("\taction:[0x%x]\n", r->action);
334 printf("\n");
337 /****************************************************************************
338 ****************************************************************************/
340 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
341 TALLOC_CTX *mem_ctx,
342 int argc, const char **argv)
344 WERROR result;
345 uint32_t level = 1;
346 union spoolss_PrinterInfo *info;
347 uint32_t i, count;
348 const char *name;
349 uint32_t flags = PRINTER_ENUM_LOCAL;
351 if (argc > 4) {
352 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
353 return WERR_OK;
356 if (argc >= 2) {
357 level = atoi(argv[1]);
360 if (argc >= 3) {
361 name = argv[2];
362 } else {
363 name = cli->srv_name_slash;
366 if (argc == 4) {
367 flags = atoi(argv[3]);
370 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
371 flags,
372 name,
373 level,
375 &count,
376 &info);
377 if (W_ERROR_IS_OK(result)) {
379 if (!count) {
380 printf ("No printers returned.\n");
381 goto done;
384 for (i = 0; i < count; i++) {
385 switch (level) {
386 case 0:
387 display_print_info0(&info[i].info0);
388 break;
389 case 1:
390 display_print_info1(&info[i].info1);
391 break;
392 case 2:
393 display_print_info2(&info[i].info2);
394 break;
395 case 3:
396 display_print_info3(&info[i].info3);
397 break;
398 case 4:
399 display_print_info4(&info[i].info4);
400 break;
401 case 5:
402 display_print_info5(&info[i].info5);
403 break;
404 case 6:
405 display_print_info6(&info[i].info6);
406 break;
407 default:
408 printf("unknown info level %d\n", level);
409 goto done;
413 done:
415 return result;
418 /****************************************************************************
419 ****************************************************************************/
421 static void display_port_info_1(struct spoolss_PortInfo1 *r)
423 printf("\tPort Name:\t[%s]\n", r->port_name);
426 /****************************************************************************
427 ****************************************************************************/
429 static void display_port_info_2(struct spoolss_PortInfo2 *r)
431 printf("\tPort Name:\t[%s]\n", r->port_name);
432 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
433 printf("\tDescription:\t[%s]\n", r->description);
434 printf("\tPort Type:\t" );
435 if (r->port_type) {
436 int comma = 0; /* hack */
437 printf( "[" );
438 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
439 printf( "Read" );
440 comma = 1;
442 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
443 printf( "%sWrite", comma ? ", " : "" );
444 comma = 1;
446 /* These two have slightly different interpretations
447 on 95/98/ME but I'm disregarding that for now */
448 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
449 printf( "%sRedirected", comma ? ", " : "" );
450 comma = 1;
452 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
453 printf( "%sNet-Attached", comma ? ", " : "" );
455 printf( "]\n" );
456 } else {
457 printf( "[Unset]\n" );
459 printf("\tReserved:\t[%d]\n", r->reserved);
460 printf("\n");
463 /****************************************************************************
464 ****************************************************************************/
466 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
467 TALLOC_CTX *mem_ctx, int argc,
468 const char **argv)
470 WERROR result;
471 uint32_t level = 1;
472 uint32_t count;
473 union spoolss_PortInfo *info;
475 if (argc > 2) {
476 printf("Usage: %s [level]\n", argv[0]);
477 return WERR_OK;
480 if (argc == 2) {
481 level = atoi(argv[1]);
484 /* Enumerate ports */
486 result = rpccli_spoolss_enumports(cli, mem_ctx,
487 cli->srv_name_slash,
488 level,
490 &count,
491 &info);
492 if (W_ERROR_IS_OK(result)) {
493 int i;
495 for (i = 0; i < count; i++) {
496 switch (level) {
497 case 1:
498 display_port_info_1(&info[i].info1);
499 break;
500 case 2:
501 display_port_info_2(&info[i].info2);
502 break;
503 default:
504 printf("unknown info level %d\n", level);
505 break;
510 return result;
513 /****************************************************************************
514 ****************************************************************************/
516 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
517 TALLOC_CTX *mem_ctx,
518 int argc, const char **argv)
520 struct policy_handle pol;
521 WERROR result;
522 NTSTATUS status;
523 uint32_t info_level = 2;
524 union spoolss_PrinterInfo info;
525 struct spoolss_SetPrinterInfoCtr info_ctr;
526 struct spoolss_SetPrinterInfo2 info2;
527 const char *printername, *comment = NULL;
528 struct spoolss_DevmodeContainer devmode_ctr;
529 struct sec_desc_buf secdesc_ctr;
530 struct dcerpc_binding_handle *b = cli->binding_handle;
532 if (argc == 1 || argc > 3) {
533 printf("Usage: %s printername comment\n", argv[0]);
535 return WERR_OK;
538 /* Open a printer handle */
539 if (argc == 3) {
540 comment = argv[2];
543 ZERO_STRUCT(devmode_ctr);
544 ZERO_STRUCT(secdesc_ctr);
546 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
548 /* get a printer handle */
549 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
550 printername,
551 PRINTER_ALL_ACCESS,
552 &pol);
553 if (!W_ERROR_IS_OK(result))
554 goto done;
556 /* Get printer info */
557 result = rpccli_spoolss_getprinter(cli, mem_ctx,
558 &pol,
559 info_level,
561 &info);
562 if (!W_ERROR_IS_OK(result))
563 goto done;
566 /* Modify the comment. */
567 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
568 info2.comment = comment;
570 info_ctr.level = 2;
571 info_ctr.info.info2 = &info2;
573 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
574 &pol,
575 &info_ctr,
576 &devmode_ctr,
577 &secdesc_ctr,
578 0, /* command */
579 &result);
580 if (!NT_STATUS_IS_OK(status)) {
581 result = ntstatus_to_werror(status);
582 goto done;
584 if (W_ERROR_IS_OK(result))
585 printf("Success in setting comment.\n");
587 done:
588 if (is_valid_policy_hnd(&pol)) {
589 WERROR _result;
590 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
593 return result;
596 /****************************************************************************
597 ****************************************************************************/
599 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
600 TALLOC_CTX *mem_ctx,
601 int argc, const char **argv)
603 struct policy_handle pol;
604 WERROR result;
605 NTSTATUS status;
606 uint32_t info_level = 2;
607 union spoolss_PrinterInfo info;
608 const char *printername,
609 *new_printername = NULL;
610 struct spoolss_SetPrinterInfoCtr info_ctr;
611 struct spoolss_SetPrinterInfo2 info2;
612 struct spoolss_DevmodeContainer devmode_ctr;
613 struct sec_desc_buf secdesc_ctr;
614 struct dcerpc_binding_handle *b = cli->binding_handle;
616 ZERO_STRUCT(devmode_ctr);
617 ZERO_STRUCT(secdesc_ctr);
619 if (argc == 1 || argc > 3) {
620 printf("Usage: %s printername new_printername\n", argv[0]);
622 return WERR_OK;
625 /* Open a printer handle */
626 if (argc == 3) {
627 new_printername = argv[2];
630 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
632 /* get a printer handle */
633 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
634 printername,
635 PRINTER_ALL_ACCESS,
636 &pol);
637 if (!W_ERROR_IS_OK(result))
638 goto done;
640 /* Get printer info */
641 result = rpccli_spoolss_getprinter(cli, mem_ctx,
642 &pol,
643 info_level,
645 &info);
646 if (!W_ERROR_IS_OK(result))
647 goto done;
649 /* Modify the printername. */
650 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
651 info2.printername = new_printername;
653 info_ctr.level = 2;
654 info_ctr.info.info2 = &info2;
656 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
657 &pol,
658 &info_ctr,
659 &devmode_ctr,
660 &secdesc_ctr,
661 0, /* command */
662 &result);
663 if (!NT_STATUS_IS_OK(status)) {
664 result = ntstatus_to_werror(status);
665 goto done;
667 if (W_ERROR_IS_OK(result))
668 printf("Success in setting printername.\n");
670 done:
671 if (is_valid_policy_hnd(&pol)) {
672 WERROR _result;
673 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
676 return result;
679 /****************************************************************************
680 ****************************************************************************/
682 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
683 TALLOC_CTX *mem_ctx,
684 int argc, const char **argv)
686 struct policy_handle pol;
687 WERROR result;
688 uint32_t level = 1;
689 const char *printername;
690 union spoolss_PrinterInfo info;
691 struct dcerpc_binding_handle *b = cli->binding_handle;
693 if (argc == 1 || argc > 3) {
694 printf("Usage: %s <printername> [level]\n", argv[0]);
695 return WERR_OK;
698 /* Open a printer handle */
699 if (argc == 3) {
700 level = atoi(argv[2]);
703 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
705 /* get a printer handle */
707 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
708 printername,
709 SEC_FLAG_MAXIMUM_ALLOWED,
710 &pol);
711 if (!W_ERROR_IS_OK(result)) {
712 goto done;
715 /* Get printer info */
717 result = rpccli_spoolss_getprinter(cli, mem_ctx,
718 &pol,
719 level,
721 &info);
722 if (!W_ERROR_IS_OK(result)) {
723 goto done;
726 /* Display printer info */
727 switch (level) {
728 case 0:
729 display_print_info0(&info.info0);
730 break;
731 case 1:
732 display_print_info1(&info.info1);
733 break;
734 case 2:
735 display_print_info2(&info.info2);
736 break;
737 case 3:
738 display_print_info3(&info.info3);
739 break;
740 case 4:
741 display_print_info4(&info.info4);
742 break;
743 case 5:
744 display_print_info5(&info.info5);
745 break;
746 case 6:
747 display_print_info6(&info.info6);
748 break;
749 case 7:
750 display_print_info7(&info.info7);
751 break;
752 default:
753 printf("unknown info level %d\n", level);
754 break;
756 done:
757 if (is_valid_policy_hnd(&pol)) {
758 WERROR _result;
759 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
762 return result;
765 /****************************************************************************
766 ****************************************************************************/
768 static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
770 const char *text = NULL;
772 switch(type) {
773 case REG_DWORD:
774 if (blob.length >= sizeof(uint32_t)) {
775 printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
776 } else {
777 printf("%s: REG_DWORD: <invalid>\n", name);
779 break;
780 case REG_SZ:
781 pull_reg_sz(talloc_tos(), &blob, &text);
782 printf("%s: REG_SZ: %s\n", name, text ? text : "");
783 break;
784 case REG_BINARY: {
785 char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
786 size_t i, len;
787 printf("%s: REG_BINARY:", name);
788 len = strlen(hex);
789 for (i=0; i<len; i++) {
790 if (hex[i] == '\0') {
791 break;
793 if (i%40 == 0) {
794 putchar('\n');
796 putchar(hex[i]);
798 TALLOC_FREE(hex);
799 putchar('\n');
800 break;
802 case REG_MULTI_SZ: {
803 uint32_t i;
804 const char **values;
806 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
807 d_printf("pull_reg_multi_sz failed\n");
808 break;
811 printf("%s: REG_MULTI_SZ: \n", name);
812 for (i=0; values[i] != NULL; i++) {
813 d_printf("%s\n", values[i]);
815 TALLOC_FREE(values);
816 break;
818 default:
819 printf("%s: unknown type %d\n", name, type);
824 /****************************************************************************
825 ****************************************************************************/
827 static void display_printer_data(const char *v,
828 enum winreg_Type type,
829 uint8_t *data,
830 uint32_t length)
832 int i;
833 union spoolss_PrinterData r;
834 DATA_BLOB blob = data_blob_const(data, length);
835 WERROR result;
836 enum ndr_err_code ndr_err;
838 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
839 if (!W_ERROR_IS_OK(result)) {
840 return;
843 switch (type) {
844 case REG_DWORD:
845 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
846 break;
847 case REG_SZ:
848 printf("%s: REG_SZ: %s\n", v, r.string);
849 break;
850 case REG_BINARY: {
851 char *hex = hex_encode_talloc(NULL,
852 r.binary.data, r.binary.length);
853 size_t len;
854 printf("%s: REG_BINARY:", v);
855 len = strlen(hex);
856 for (i=0; i<len; i++) {
857 if (hex[i] == '\0') {
858 break;
860 if (i%40 == 0) {
861 putchar('\n');
863 putchar(hex[i]);
865 TALLOC_FREE(hex);
866 putchar('\n');
867 putchar('\n');
869 if (strequal(v, "OsVersion")) {
870 struct spoolss_OSVersion os;
871 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
872 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
873 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
874 // add output here;
875 printf("OsMajor: %u\n", os.major);
876 printf("OsMinor: %u\n", os.minor);
877 printf("OsBuild: %u\n", os.build);
878 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
881 if (strequal(v, "OsVersionEx")) {
882 struct spoolss_OSVersionEx os;
883 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
884 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
885 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
886 printf("OsMajor: %u\n", os.major);
887 printf("OsMinor: %u\n", os.minor);
888 printf("OsBuild: %u\n", os.build);
889 printf("ServicePackMajor: %u\n", os.service_pack_major);
890 printf("ServicePackMinor: %u\n", os.service_pack_minor);
891 NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
894 break;
896 case REG_MULTI_SZ:
897 printf("%s: REG_MULTI_SZ: ", v);
898 for (i=0; r.string_array[i] != NULL; i++) {
899 printf("%s ", r.string_array[i]);
901 printf("\n");
902 break;
903 default:
904 printf("%s: unknown type 0x%02x:\n", v, type);
905 break;
909 /****************************************************************************
910 ****************************************************************************/
912 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
913 TALLOC_CTX *mem_ctx,
914 int argc, const char **argv)
916 struct policy_handle pol;
917 WERROR result;
918 fstring printername;
919 const char *valuename;
920 enum winreg_Type type;
921 uint8_t *data;
922 uint32_t needed;
923 struct dcerpc_binding_handle *b = cli->binding_handle;
925 if (argc != 3) {
926 printf("Usage: %s <printername> <valuename>\n", argv[0]);
927 printf("<printername> of . queries print server\n");
928 return WERR_OK;
930 valuename = argv[2];
932 /* Open a printer handle */
934 if (strncmp(argv[1], ".", sizeof(".")) == 0)
935 fstrcpy(printername, cli->srv_name_slash);
936 else
937 slprintf(printername, sizeof(printername)-1, "%s\\%s",
938 cli->srv_name_slash, argv[1]);
940 /* get a printer handle */
942 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
943 printername,
944 SEC_FLAG_MAXIMUM_ALLOWED,
945 &pol);
946 if (!W_ERROR_IS_OK(result))
947 goto done;
949 /* Get printer info */
951 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
952 &pol,
953 valuename,
955 &type,
956 &needed,
957 &data);
958 if (!W_ERROR_IS_OK(result))
959 goto done;
961 /* Display printer data */
963 display_printer_data(valuename, type, data, needed);
965 done:
966 if (is_valid_policy_hnd(&pol)) {
967 WERROR _result;
968 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
971 return result;
974 /****************************************************************************
975 ****************************************************************************/
977 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
978 TALLOC_CTX *mem_ctx,
979 int argc, const char **argv)
981 struct policy_handle pol;
982 WERROR result;
983 NTSTATUS status;
984 fstring printername;
985 const char *valuename, *keyname;
987 enum winreg_Type type;
988 uint8_t *data = NULL;
989 uint32_t offered = 0;
990 uint32_t needed;
991 struct dcerpc_binding_handle *b = cli->binding_handle;
993 if (argc != 4) {
994 printf("Usage: %s <printername> <keyname> <valuename>\n",
995 argv[0]);
996 printf("<printername> of . queries print server\n");
997 return WERR_OK;
999 valuename = argv[3];
1000 keyname = argv[2];
1002 /* Open a printer handle */
1004 if (strncmp(argv[1], ".", sizeof(".")) == 0)
1005 fstrcpy(printername, cli->srv_name_slash);
1006 else
1007 slprintf(printername, sizeof(printername)-1, "%s\\%s",
1008 cli->srv_name_slash, argv[1]);
1010 /* get a printer handle */
1012 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1013 printername,
1014 SEC_FLAG_MAXIMUM_ALLOWED,
1015 &pol);
1016 if (!W_ERROR_IS_OK(result))
1017 goto done;
1019 /* Get printer info */
1021 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1022 if (!data) {
1023 goto done;
1026 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1027 &pol,
1028 keyname,
1029 valuename,
1030 &type,
1031 data,
1032 offered,
1033 &needed,
1034 &result);
1035 if (!NT_STATUS_IS_OK(status)) {
1036 result = ntstatus_to_werror(status);
1037 goto done;
1039 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1040 offered = needed;
1041 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1042 if (!data) {
1043 goto done;
1045 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1046 &pol,
1047 keyname,
1048 valuename,
1049 &type,
1050 data,
1051 offered,
1052 &needed,
1053 &result);
1056 if (!NT_STATUS_IS_OK(status)) {
1057 result = ntstatus_to_werror(status);
1058 goto done;
1061 if (!W_ERROR_IS_OK(result))
1062 goto done;
1064 /* Display printer data */
1066 display_printer_data(valuename, type, data, needed);
1069 done:
1070 if (is_valid_policy_hnd(&pol)) {
1071 WERROR _result;
1072 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1075 return result;
1078 /****************************************************************************
1079 ****************************************************************************/
1081 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1083 if (!r) {
1084 return;
1087 printf("Printer Driver Info 1:\n");
1088 printf("\tDriver Name: [%s]\n", r->driver_name);
1089 printf("\n");
1092 /****************************************************************************
1093 ****************************************************************************/
1095 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1097 if (!r) {
1098 return;
1101 printf("Printer Driver Info 2:\n");
1102 printf("\tVersion: [%x]\n", r->version);
1103 printf("\tDriver Name: [%s]\n", r->driver_name);
1104 printf("\tArchitecture: [%s]\n", r->architecture);
1105 printf("\tDriver Path: [%s]\n", r->driver_path);
1106 printf("\tDatafile: [%s]\n", r->data_file);
1107 printf("\tConfigfile: [%s]\n", r->config_file);
1108 printf("\n");
1111 /****************************************************************************
1112 ****************************************************************************/
1114 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1116 int i;
1118 if (!r) {
1119 return;
1122 printf("Printer Driver Info 3:\n");
1123 printf("\tVersion: [%x]\n", r->version);
1124 printf("\tDriver Name: [%s]\n", r->driver_name);
1125 printf("\tArchitecture: [%s]\n", r->architecture);
1126 printf("\tDriver Path: [%s]\n", r->driver_path);
1127 printf("\tDatafile: [%s]\n", r->data_file);
1128 printf("\tConfigfile: [%s]\n", r->config_file);
1129 printf("\tHelpfile: [%s]\n", r->help_file);
1131 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1132 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1135 printf("\tMonitorname: [%s]\n", r->monitor_name);
1136 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1137 printf("\n");
1140 /****************************************************************************
1141 ****************************************************************************/
1143 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1145 int i;
1147 if (!r) {
1148 return;
1151 printf("Printer Driver Info 4:\n");
1152 printf("\tVersion: [%x]\n", r->version);
1153 printf("\tDriver Name: [%s]\n", r->driver_name);
1154 printf("\tArchitecture: [%s]\n", r->architecture);
1155 printf("\tDriver Path: [%s]\n", r->driver_path);
1156 printf("\tDatafile: [%s]\n", r->data_file);
1157 printf("\tConfigfile: [%s]\n", r->config_file);
1158 printf("\tHelpfile: [%s]\n", r->help_file);
1160 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1161 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1164 printf("\tMonitorname: [%s]\n", r->monitor_name);
1165 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1167 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1168 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1170 printf("\n");
1173 /****************************************************************************
1174 ****************************************************************************/
1176 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1178 if (!r) {
1179 return;
1182 printf("Printer Driver Info 5:\n");
1183 printf("\tVersion: [%x]\n", r->version);
1184 printf("\tDriver Name: [%s]\n", r->driver_name);
1185 printf("\tArchitecture: [%s]\n", r->architecture);
1186 printf("\tDriver Path: [%s]\n", r->driver_path);
1187 printf("\tDatafile: [%s]\n", r->data_file);
1188 printf("\tConfigfile: [%s]\n", r->config_file);
1189 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1190 printf("\tConfig Version: [0x%x]\n", r->config_version);
1191 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1192 printf("\n");
1195 /****************************************************************************
1196 ****************************************************************************/
1198 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1200 int i;
1202 if (!r) {
1203 return;
1206 printf("Printer Driver Info 6:\n");
1207 printf("\tVersion: [%x]\n", r->version);
1208 printf("\tDriver Name: [%s]\n", r->driver_name);
1209 printf("\tArchitecture: [%s]\n", r->architecture);
1210 printf("\tDriver Path: [%s]\n", r->driver_path);
1211 printf("\tDatafile: [%s]\n", r->data_file);
1212 printf("\tConfigfile: [%s]\n", r->config_file);
1213 printf("\tHelpfile: [%s]\n", r->help_file);
1215 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1216 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1219 printf("\tMonitorname: [%s]\n", r->monitor_name);
1220 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1222 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1223 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1226 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1227 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1228 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1229 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1230 printf("\tHardware ID: [%s]\n", r->hardware_id);
1231 printf("\tProvider: [%s]\n", r->provider);
1233 printf("\n");
1236 /****************************************************************************
1237 ****************************************************************************/
1239 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1241 int i;
1243 if (!r) {
1244 return;
1247 printf("Printer Driver Info 8:\n");
1248 printf("\tVersion: [%x]\n", r->version);
1249 printf("\tDriver Name: [%s]\n", r->driver_name);
1250 printf("\tArchitecture: [%s]\n", r->architecture);
1251 printf("\tDriver Path: [%s]\n", r->driver_path);
1252 printf("\tDatafile: [%s]\n", r->data_file);
1253 printf("\tConfigfile: [%s]\n", r->config_file);
1254 printf("\tHelpfile: [%s]\n", r->help_file);
1255 printf("\tMonitorname: [%s]\n", r->monitor_name);
1256 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1258 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1259 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1262 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1263 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1266 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1267 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1268 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1269 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1270 printf("\tHardware ID: [%s]\n", r->hardware_id);
1271 printf("\tProvider: [%s]\n", r->provider);
1272 printf("\tPrint Processor: [%s]\n", r->print_processor);
1273 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1274 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1275 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1277 printf("\tInf Path: [%s]\n", r->inf_path);
1278 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1279 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1280 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1282 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1283 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1284 (long long unsigned int)r->min_inbox_driver_ver_version);
1286 printf("\n");
1289 /****************************************************************************
1290 ****************************************************************************/
1292 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1293 TALLOC_CTX *mem_ctx,
1294 int argc, const char **argv)
1296 struct policy_handle pol;
1297 WERROR werror;
1298 uint32_t level = 3;
1299 const char *printername;
1300 uint32_t i;
1301 bool success = false;
1302 union spoolss_DriverInfo info;
1303 uint32_t server_major_version;
1304 uint32_t server_minor_version;
1305 struct dcerpc_binding_handle *b = cli->binding_handle;
1307 if ((argc == 1) || (argc > 3)) {
1308 printf("Usage: %s <printername> [level]\n", argv[0]);
1309 return WERR_OK;
1312 /* get the arguments need to open the printer handle */
1314 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1316 if (argc == 3) {
1317 level = atoi(argv[2]);
1320 /* Open a printer handle */
1322 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1323 printername,
1324 PRINTER_ACCESS_USE,
1325 &pol);
1326 if (!W_ERROR_IS_OK(werror)) {
1327 printf("Error opening printer handle for %s!\n", printername);
1328 return werror;
1331 /* loop through and print driver info level for each architecture */
1333 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1335 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1336 &pol,
1337 archi_table[i].long_archi,
1338 level,
1339 0, /* offered */
1340 archi_table[i].version,
1342 &info,
1343 &server_major_version,
1344 &server_minor_version);
1345 if (!W_ERROR_IS_OK(werror)) {
1346 continue;
1349 /* need at least one success */
1351 success = true;
1353 printf("\n[%s]\n", archi_table[i].long_archi);
1355 switch (level) {
1356 case 1:
1357 display_print_driver1(&info.info1);
1358 break;
1359 case 2:
1360 display_print_driver2(&info.info2);
1361 break;
1362 case 3:
1363 display_print_driver3(&info.info3);
1364 break;
1365 case 4:
1366 display_print_driver4(&info.info4);
1367 break;
1368 case 5:
1369 display_print_driver5(&info.info5);
1370 break;
1371 case 6:
1372 display_print_driver6(&info.info6);
1373 break;
1374 case 8:
1375 display_print_driver8(&info.info8);
1376 break;
1377 default:
1378 printf("unknown info level %d\n", level);
1379 break;
1383 /* Cleanup */
1385 if (is_valid_policy_hnd(&pol)) {
1386 WERROR _result;
1387 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1390 if (success) {
1391 werror = WERR_OK;
1394 return werror;
1397 /****************************************************************************
1398 ****************************************************************************/
1400 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1401 TALLOC_CTX *mem_ctx,
1402 const char *architecture,
1403 uint32_t level)
1405 WERROR werror;
1406 uint32_t count = 0;
1407 union spoolss_DriverInfo *info = NULL;
1408 uint32_t j;
1410 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1411 cli->srv_name_slash,
1412 architecture,
1413 level,
1415 &count,
1416 &info);
1418 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1419 printf("Server does not support environment [%s]\n",
1420 architecture);
1421 return WERR_OK;
1424 if (count == 0) {
1425 return WERR_OK;
1428 if (!W_ERROR_IS_OK(werror)) {
1429 printf("Error getting driver for environment [%s] - %s\n",
1430 architecture, win_errstr(werror));
1431 return werror;
1434 printf("\n[%s]\n", architecture);
1436 switch (level) {
1437 case 1:
1438 for (j=0; j < count; j++) {
1439 display_print_driver1(&info[j].info1);
1441 break;
1442 case 2:
1443 for (j=0; j < count; j++) {
1444 display_print_driver2(&info[j].info2);
1446 break;
1447 case 3:
1448 for (j=0; j < count; j++) {
1449 display_print_driver3(&info[j].info3);
1451 break;
1452 case 4:
1453 for (j=0; j < count; j++) {
1454 display_print_driver4(&info[j].info4);
1456 break;
1457 case 5:
1458 for (j=0; j < count; j++) {
1459 display_print_driver5(&info[j].info5);
1461 break;
1462 case 6:
1463 for (j=0; j < count; j++) {
1464 display_print_driver6(&info[j].info6);
1466 break;
1467 case 8:
1468 for (j=0; j < count; j++) {
1469 display_print_driver8(&info[j].info8);
1471 break;
1472 default:
1473 printf("unknown info level %d\n", level);
1474 return WERR_INVALID_LEVEL;
1477 return werror;
1480 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1481 TALLOC_CTX *mem_ctx,
1482 int argc, const char **argv)
1484 WERROR werror = WERR_OK;
1485 uint32_t level = 1;
1486 uint32_t i;
1487 const char *architecture = NULL;
1489 if (argc > 3) {
1490 printf("Usage: enumdrivers [level] [architecture]\n");
1491 return WERR_OK;
1494 if (argc >= 2) {
1495 level = atoi(argv[1]);
1498 if (argc == 3) {
1499 architecture = argv[2];
1502 if (architecture) {
1503 return enum_driver_by_architecture(cli, mem_ctx,
1504 architecture,
1505 level);
1508 /* loop through and print driver info level for each architecture */
1509 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1510 /* check to see if we already asked for this architecture string */
1512 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1513 continue;
1516 werror = enum_driver_by_architecture(cli, mem_ctx,
1517 archi_table[i].long_archi,
1518 level);
1519 if (!W_ERROR_IS_OK(werror)) {
1520 break;
1524 return werror;
1527 /****************************************************************************
1528 ****************************************************************************/
1530 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1532 printf("\tDirectory Name:[%s]\n", r->directory_name);
1535 /****************************************************************************
1536 ****************************************************************************/
1538 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1539 TALLOC_CTX *mem_ctx,
1540 int argc, const char **argv)
1542 WERROR result;
1543 NTSTATUS status;
1544 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1545 DATA_BLOB buffer;
1546 uint32_t offered;
1547 union spoolss_DriverDirectoryInfo info;
1548 uint32_t needed;
1549 struct dcerpc_binding_handle *b = cli->binding_handle;
1551 if (argc > 2) {
1552 printf("Usage: %s [environment]\n", argv[0]);
1553 return WERR_OK;
1556 /* Get the arguments need to open the printer handle */
1558 if (argc == 2) {
1559 env = argv[1];
1562 /* Get the directory. Only use Info level 1 */
1564 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1565 cli->srv_name_slash,
1566 env,
1568 NULL, /* buffer */
1569 0, /* offered */
1570 NULL, /* info */
1571 &needed,
1572 &result);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 return ntstatus_to_werror(status);
1576 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1577 offered = needed;
1578 buffer = data_blob_talloc_zero(mem_ctx, needed);
1580 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1581 cli->srv_name_slash,
1582 env,
1584 &buffer,
1585 offered,
1586 &info,
1587 &needed,
1588 &result);
1589 if (!NT_STATUS_IS_OK(status)) {
1590 return ntstatus_to_werror(status);
1594 if (W_ERROR_IS_OK(result)) {
1595 display_printdriverdir_1(&info.info1);
1598 return result;
1601 /****************************************************************************
1602 ****************************************************************************/
1604 static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
1605 TALLOC_CTX *mem_ctx,
1606 int argc, const char **argv)
1608 HRESULT hresult;
1609 NTSTATUS status;
1610 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1611 uint32_t offered;
1612 uint32_t needed;
1613 struct dcerpc_binding_handle *b = cli->binding_handle;
1614 const char *package_id = "";
1615 const char *cab = NULL;
1617 if (argc > 4) {
1618 printf("Usage: %s [environment] [package_id]\n", argv[0]);
1619 return WERR_OK;
1622 /* Get the arguments need to open the printer handle */
1624 if (argc >= 2) {
1625 env = argv[1];
1628 if (argc == 3) {
1629 package_id = argv[2];
1632 offered = 1;
1633 cab = talloc_zero_array(mem_ctx, char, offered);
1634 if (cab == NULL) {
1635 return WERR_NOT_ENOUGH_MEMORY;
1637 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1638 cli->srv_name_slash,
1639 env,
1640 NULL,
1641 package_id,
1642 cab,
1643 offered,
1644 &needed,
1645 &hresult);
1646 if (!NT_STATUS_IS_OK(status)) {
1647 return ntstatus_to_werror(status);
1650 if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
1651 offered = needed;
1652 cab = talloc_zero_array(mem_ctx, char, offered);
1653 if (cab == NULL) {
1654 return WERR_NOT_ENOUGH_MEMORY;
1656 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1657 cli->srv_name_slash,
1658 env,
1659 NULL,
1660 package_id,
1661 cab,
1662 offered,
1663 &needed,
1664 &hresult);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 return ntstatus_to_werror(status);
1670 return W_ERROR(WIN32_FROM_HRESULT(hresult));
1674 /****************************************************************************
1675 ****************************************************************************/
1677 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1678 struct spoolss_AddDriverInfo3 *info,
1679 const char *arch)
1682 int i;
1684 for (i=0; archi_table[i].long_archi != NULL; i++)
1686 if (strcmp(arch, archi_table[i].short_archi) == 0)
1688 info->version = archi_table[i].version;
1689 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1690 break;
1694 if (archi_table[i].long_archi == NULL)
1696 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1699 return;
1703 /**************************************************************************
1704 wrapper for strtok to get the next parameter from a delimited list.
1705 Needed to handle the empty parameter string denoted by "NULL"
1706 *************************************************************************/
1708 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1709 const char *delim, const char **dest,
1710 char **saveptr)
1712 char *ptr;
1714 /* get the next token */
1715 ptr = strtok_r(str, delim, saveptr);
1717 /* a string of 'NULL' is used to represent an empty
1718 parameter because two consecutive delimiters
1719 will not return an empty string. See man strtok(3)
1720 for details */
1721 if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1722 ptr = NULL;
1725 if (dest != NULL) {
1726 *dest = talloc_strdup(mem_ctx, ptr);
1729 return ptr;
1732 /********************************************************************************
1733 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1734 string in the form of
1735 <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1736 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1737 <Default Data Type>:<Comma Separated list of Files>
1738 *******************************************************************************/
1740 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1741 char *args)
1743 char *str, *str2;
1744 size_t count = 0;
1745 char *saveptr = NULL;
1746 struct spoolss_StringArray *deps;
1747 const char **file_array = NULL;
1748 int i;
1750 /* fill in the UNISTR fields */
1751 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1752 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1753 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1754 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1755 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1756 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1757 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1759 /* <Comma Separated List of Dependent Files> */
1760 /* save the beginning of the string */
1761 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1762 str = str2;
1764 /* begin to strip out each filename */
1765 str = strtok_r(str, ",", &saveptr);
1767 /* no dependent files, we are done */
1768 if (!str) {
1769 return true;
1772 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1773 if (!deps) {
1774 return false;
1777 while (str != NULL) {
1778 bool ok;
1779 ok = add_string_to_array(deps, str, &file_array, &count);
1780 if (!ok) {
1781 return false;
1783 str = strtok_r(NULL, ",", &saveptr);
1786 deps->string = talloc_zero_array(deps, const char *, count + 1);
1787 if (!deps->string) {
1788 return false;
1791 for (i=0; i < count; i++) {
1792 deps->string[i] = file_array[i];
1795 r->dependent_files = deps;
1797 return true;
1800 /****************************************************************************
1801 ****************************************************************************/
1803 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1804 TALLOC_CTX *mem_ctx,
1805 int argc, const char **argv)
1807 WERROR result;
1808 NTSTATUS status;
1809 uint32_t level = 3;
1810 struct spoolss_AddDriverInfoCtr info_ctr;
1811 struct spoolss_AddDriverInfo3 info3;
1812 const char *arch;
1813 char *driver_args;
1814 struct dcerpc_binding_handle *b = cli->binding_handle;
1816 /* parse the command arguments */
1817 if (argc != 3 && argc != 4)
1819 printf ("Usage: %s <Environment> \\\n", argv[0]);
1820 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1821 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1822 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1823 printf ("\t[version]\n");
1825 return WERR_OK;
1828 /* Fill in the spoolss_AddDriverInfo3 struct */
1829 ZERO_STRUCT(info3);
1831 arch = cmd_spoolss_get_short_archi(argv[1]);
1832 if (!arch) {
1833 printf ("Error Unknown architecture [%s]\n", argv[1]);
1834 return WERR_INVALID_PARAMETER;
1837 set_drv_info_3_env(mem_ctx, &info3, arch);
1839 driver_args = talloc_strdup( mem_ctx, argv[2] );
1840 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1842 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1843 return WERR_INVALID_PARAMETER;
1846 /* if printer driver version specified, override the default version
1847 * used by the architecture. This allows installation of Windows
1848 * 2000 (version 3) printer drivers. */
1849 if (argc == 4)
1851 info3.version = atoi(argv[3]);
1855 info_ctr.level = level;
1856 info_ctr.info.info3 = &info3;
1858 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1859 cli->srv_name_slash,
1860 &info_ctr,
1861 &result);
1862 if (!NT_STATUS_IS_OK(status)) {
1863 return ntstatus_to_werror(status);
1865 if (W_ERROR_IS_OK(result)) {
1866 printf ("Printer Driver %s successfully installed.\n",
1867 info3.driver_name);
1870 return result;
1874 /****************************************************************************
1875 ****************************************************************************/
1877 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1878 TALLOC_CTX *mem_ctx,
1879 int argc, const char **argv)
1881 WERROR result;
1882 struct spoolss_SetPrinterInfoCtr info_ctr;
1883 struct spoolss_SetPrinterInfo2 info2;
1885 /* parse the command arguments */
1886 if (argc != 5)
1888 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1889 return WERR_OK;
1892 /* Fill in the DRIVER_INFO_2 struct */
1893 ZERO_STRUCT(info2);
1895 info2.printername = argv[1];
1896 info2.drivername = argv[3];
1897 info2.sharename = argv[2];
1898 info2.portname = argv[4];
1899 info2.comment = "Created by rpcclient";
1900 info2.printprocessor = "winprint";
1901 info2.datatype = "RAW";
1902 info2.devmode_ptr = 0;
1903 info2.secdesc_ptr = 0;
1904 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1905 info2.priority = 0;
1906 info2.defaultpriority = 0;
1907 info2.starttime = 0;
1908 info2.untiltime = 0;
1910 /* These three fields must not be used by AddPrinter()
1911 as defined in the MS Platform SDK documentation..
1912 --jerry
1913 info2.status = 0;
1914 info2.cjobs = 0;
1915 info2.averageppm = 0;
1918 info_ctr.level = 2;
1919 info_ctr.info.info2 = &info2;
1921 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1922 &info_ctr);
1923 if (W_ERROR_IS_OK(result))
1924 printf ("Printer %s successfully installed.\n", argv[1]);
1926 return result;
1929 /****************************************************************************
1930 ****************************************************************************/
1932 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1933 TALLOC_CTX *mem_ctx,
1934 int argc, const char **argv)
1936 struct policy_handle pol;
1937 WERROR result;
1938 NTSTATUS status;
1939 uint32_t level = 2;
1940 const char *printername;
1941 union spoolss_PrinterInfo info;
1942 struct spoolss_SetPrinterInfoCtr info_ctr;
1943 struct spoolss_SetPrinterInfo2 info2;
1944 struct spoolss_DevmodeContainer devmode_ctr;
1945 struct sec_desc_buf secdesc_ctr;
1946 struct dcerpc_binding_handle *b = cli->binding_handle;
1948 ZERO_STRUCT(devmode_ctr);
1949 ZERO_STRUCT(secdesc_ctr);
1951 /* parse the command arguments */
1952 if (argc != 3)
1954 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1955 return WERR_OK;
1958 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1960 /* Get a printer handle */
1962 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1963 printername,
1964 PRINTER_ALL_ACCESS,
1965 &pol);
1966 if (!W_ERROR_IS_OK(result))
1967 goto done;
1969 /* Get printer info */
1971 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1972 &pol,
1973 level,
1975 &info);
1976 if (!W_ERROR_IS_OK(result)) {
1977 printf ("Unable to retrieve printer information!\n");
1978 goto done;
1981 /* Set the printer driver */
1983 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1984 info2.drivername = argv[2];
1986 info_ctr.level = 2;
1987 info_ctr.info.info2 = &info2;
1989 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1990 &pol,
1991 &info_ctr,
1992 &devmode_ctr,
1993 &secdesc_ctr,
1994 0, /* command */
1995 &result);
1996 if (!NT_STATUS_IS_OK(status)) {
1997 result = ntstatus_to_werror(status);
1998 goto done;
2000 if (!W_ERROR_IS_OK(result)) {
2001 printf("SetPrinter call failed!\n");
2002 goto done;
2005 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
2007 done:
2008 /* Cleanup */
2010 if (is_valid_policy_hnd(&pol)) {
2011 WERROR _result;
2012 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2015 return result;
2019 /****************************************************************************
2020 ****************************************************************************/
2022 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
2023 TALLOC_CTX *mem_ctx,
2024 int argc, const char **argv)
2026 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
2027 NTSTATUS status;
2028 struct dcerpc_binding_handle *b = cli->binding_handle;
2030 int i;
2031 int vers = -1;
2033 const char *arch = NULL;
2034 uint32_t delete_flags = 0;
2036 /* parse the command arguments */
2037 if (argc < 2 || argc > 5) {
2038 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
2039 return WERR_OK;
2042 if (argc >= 3)
2043 arch = argv[2];
2044 if (argc >= 4) {
2045 vers = atoi(argv[3]);
2046 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
2048 if (argc == 5)
2049 delete_flags = atoi(argv[4]);
2051 /* delete the driver for all architectures */
2052 for (i=0; archi_table[i].long_archi; i++) {
2054 if (arch && !strequal(archi_table[i].long_archi, arch))
2055 continue;
2057 if (vers >= 0 && archi_table[i].version != vers)
2058 continue;
2060 /* make the call to remove the driver */
2061 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
2062 cli->srv_name_slash,
2063 archi_table[i].long_archi,
2064 argv[1],
2065 delete_flags,
2066 archi_table[i].version,
2067 &result);
2068 if (!NT_STATUS_IS_OK(status)) {
2069 return ntstatus_to_werror(status);
2071 if ( !W_ERROR_IS_OK(result) )
2073 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2074 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2075 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
2078 else
2080 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
2081 archi_table[i].long_archi, archi_table[i].version);
2082 ret = WERR_OK;
2086 return ret;
2090 /****************************************************************************
2091 ****************************************************************************/
2093 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2094 TALLOC_CTX *mem_ctx,
2095 int argc, const char **argv)
2097 WERROR result = WERR_OK;
2098 NTSTATUS status;
2099 int i;
2100 struct dcerpc_binding_handle *b = cli->binding_handle;
2102 /* parse the command arguments */
2103 if (argc != 2) {
2104 printf ("Usage: %s <driver>\n", argv[0]);
2105 return WERR_OK;
2108 /* delete the driver for all architectures */
2109 for (i=0; archi_table[i].long_archi; i++) {
2110 result = WERR_OK;
2112 /* make the call to remove the driver */
2113 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2114 cli->srv_name_slash,
2115 archi_table[i].long_archi,
2116 argv[1],
2117 &result);
2118 if (!NT_STATUS_IS_OK(status)) {
2119 result = ntstatus_to_werror(status);
2120 continue;
2122 if ( !W_ERROR_IS_OK(result) ) {
2123 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2124 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2125 argv[1], archi_table[i].long_archi,
2126 win_errstr(result));
2128 } else {
2129 printf ("Driver %s removed for arch [%s].\n", argv[1],
2130 archi_table[i].long_archi);
2134 return result;
2137 /****************************************************************************
2138 ****************************************************************************/
2140 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2141 TALLOC_CTX *mem_ctx,
2142 int argc, const char **argv)
2144 WERROR result;
2145 NTSTATUS status;
2146 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2147 DATA_BLOB buffer;
2148 uint32_t offered;
2149 union spoolss_PrintProcessorDirectoryInfo info;
2150 uint32_t needed;
2151 struct dcerpc_binding_handle *b = cli->binding_handle;
2153 /* parse the command arguments */
2154 if (argc > 2) {
2155 printf ("Usage: %s [environment]\n", argv[0]);
2156 return WERR_OK;
2159 if (argc == 2) {
2160 environment = argv[1];
2163 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2164 cli->srv_name_slash,
2165 environment,
2167 NULL, /* buffer */
2168 0, /* offered */
2169 NULL, /* info */
2170 &needed,
2171 &result);
2172 if (!NT_STATUS_IS_OK(status)) {
2173 return ntstatus_to_werror(status);
2175 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2176 offered = needed;
2177 buffer = data_blob_talloc_zero(mem_ctx, needed);
2179 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2180 cli->srv_name_slash,
2181 environment,
2183 &buffer,
2184 offered,
2185 &info,
2186 &needed,
2187 &result);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 return ntstatus_to_werror(status);
2193 if (W_ERROR_IS_OK(result)) {
2194 printf("%s\n", info.info1.directory_name);
2197 return result;
2200 /****************************************************************************
2201 ****************************************************************************/
2203 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2204 int argc, const char **argv)
2206 struct policy_handle handle;
2207 WERROR werror;
2208 NTSTATUS status;
2209 const char *printername;
2210 struct spoolss_AddFormInfoCtr info_ctr;
2211 struct spoolss_AddFormInfo1 info1;
2212 struct spoolss_AddFormInfo2 info2;
2213 uint32_t level = 1;
2214 struct dcerpc_binding_handle *b = cli->binding_handle;
2216 /* Parse the command arguments */
2218 if (argc < 3 || argc > 5) {
2219 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2220 return WERR_OK;
2223 /* Get a printer handle */
2225 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2227 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2228 printername,
2229 PRINTER_ALL_ACCESS,
2230 &handle);
2231 if (!W_ERROR_IS_OK(werror))
2232 goto done;
2234 /* Dummy up some values for the form data */
2236 if (argc == 4) {
2237 level = atoi(argv[3]);
2240 switch (level) {
2241 case 1:
2242 info1.flags = SPOOLSS_FORM_USER;
2243 info1.form_name = argv[2];
2244 info1.size.width = 100;
2245 info1.size.height = 100;
2246 info1.area.left = 0;
2247 info1.area.top = 10;
2248 info1.area.right = 20;
2249 info1.area.bottom = 30;
2251 info_ctr.level = 1;
2252 info_ctr.info.info1 = &info1;
2254 break;
2255 case 2:
2256 info2.flags = SPOOLSS_FORM_USER;
2257 info2.form_name = argv[2];
2258 info2.size.width = 100;
2259 info2.size.height = 100;
2260 info2.area.left = 0;
2261 info2.area.top = 10;
2262 info2.area.right = 20;
2263 info2.area.bottom = 30;
2264 info2.keyword = argv[2];
2265 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2266 info2.mui_dll = NULL;
2267 info2.ressource_id = 0;
2268 info2.display_name = argv[2];
2269 info2.lang_id = 0;
2271 info_ctr.level = 2;
2272 info_ctr.info.info2 = &info2;
2274 break;
2275 default:
2276 werror = WERR_INVALID_PARAMETER;
2277 goto done;
2280 /* Add the form */
2282 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2283 &handle,
2284 &info_ctr,
2285 &werror);
2286 if (!NT_STATUS_IS_OK(status)) {
2287 werror = ntstatus_to_werror(status);
2288 goto done;
2290 done:
2291 if (is_valid_policy_hnd(&handle)) {
2292 WERROR _result;
2293 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2296 return werror;
2299 /****************************************************************************
2300 ****************************************************************************/
2302 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2303 int argc, const char **argv)
2305 struct policy_handle handle;
2306 WERROR werror;
2307 NTSTATUS status;
2308 const char *printername;
2309 struct spoolss_AddFormInfoCtr info_ctr;
2310 struct spoolss_AddFormInfo1 info1;
2311 struct dcerpc_binding_handle *b = cli->binding_handle;
2313 /* Parse the command arguments */
2315 if (argc != 3) {
2316 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2317 return WERR_OK;
2320 /* Get a printer handle */
2322 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2324 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2325 printername,
2326 SEC_FLAG_MAXIMUM_ALLOWED,
2327 &handle);
2328 if (!W_ERROR_IS_OK(werror))
2329 goto done;
2331 /* Dummy up some values for the form data */
2333 info1.flags = SPOOLSS_FORM_PRINTER;
2334 info1.size.width = 100;
2335 info1.size.height = 100;
2336 info1.area.left = 0;
2337 info1.area.top = 1000;
2338 info1.area.right = 2000;
2339 info1.area.bottom = 3000;
2340 info1.form_name = argv[2];
2342 info_ctr.info.info1 = &info1;
2343 info_ctr.level = 1;
2345 /* Set the form */
2347 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2348 &handle,
2349 argv[2],
2350 &info_ctr,
2351 &werror);
2352 if (!NT_STATUS_IS_OK(status)) {
2353 werror = ntstatus_to_werror(status);
2354 goto done;
2356 done:
2357 if (is_valid_policy_hnd(&handle)) {
2358 WERROR _result;
2359 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2362 return werror;
2365 /****************************************************************************
2366 ****************************************************************************/
2368 static const char *get_form_flag(int form_flag)
2370 switch (form_flag) {
2371 case SPOOLSS_FORM_USER:
2372 return "FORM_USER";
2373 case SPOOLSS_FORM_BUILTIN:
2374 return "FORM_BUILTIN";
2375 case SPOOLSS_FORM_PRINTER:
2376 return "FORM_PRINTER";
2377 default:
2378 return "unknown";
2382 /****************************************************************************
2383 ****************************************************************************/
2385 static void display_form_info1(struct spoolss_FormInfo1 *r)
2387 printf("%s\n" \
2388 "\tflag: %s (%d)\n" \
2389 "\twidth: %d, length: %d\n" \
2390 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2391 r->form_name, get_form_flag(r->flags), r->flags,
2392 r->size.width, r->size.height,
2393 r->area.left, r->area.right,
2394 r->area.top, r->area.bottom);
2397 /****************************************************************************
2398 ****************************************************************************/
2400 static void display_form_info2(struct spoolss_FormInfo2 *r)
2402 printf("%s\n" \
2403 "\tflag: %s (%d)\n" \
2404 "\twidth: %d, length: %d\n" \
2405 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2406 r->form_name, get_form_flag(r->flags), r->flags,
2407 r->size.width, r->size.height,
2408 r->area.left, r->area.right,
2409 r->area.top, r->area.bottom);
2410 printf("\tkeyword: %s\n", r->keyword);
2411 printf("\tstring_type: 0x%08x\n", r->string_type);
2412 printf("\tmui_dll: %s\n", r->mui_dll);
2413 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2414 printf("\tdisplay_name: %s\n", r->display_name);
2415 printf("\tlang_id: %d\n", r->lang_id);
2416 printf("\n");
2419 /****************************************************************************
2420 ****************************************************************************/
2422 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2423 int argc, const char **argv)
2425 struct policy_handle handle;
2426 WERROR werror;
2427 NTSTATUS status;
2428 const char *printername;
2429 DATA_BLOB buffer;
2430 uint32_t offered = 0;
2431 union spoolss_FormInfo info;
2432 uint32_t needed;
2433 uint32_t level = 1;
2434 struct dcerpc_binding_handle *b = cli->binding_handle;
2436 /* Parse the command arguments */
2438 if (argc < 3 || argc > 5) {
2439 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2440 return WERR_OK;
2443 /* Get a printer handle */
2445 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2447 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2448 printername,
2449 SEC_FLAG_MAXIMUM_ALLOWED,
2450 &handle);
2451 if (!W_ERROR_IS_OK(werror))
2452 goto done;
2454 if (argc == 4) {
2455 level = atoi(argv[3]);
2458 /* Get the form */
2460 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2461 &handle,
2462 argv[2],
2463 level,
2464 NULL,
2465 offered,
2466 &info,
2467 &needed,
2468 &werror);
2469 if (!NT_STATUS_IS_OK(status)) {
2470 werror = ntstatus_to_werror(status);
2471 goto done;
2473 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2474 buffer = data_blob_talloc_zero(mem_ctx, needed);
2475 offered = needed;
2476 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2477 &handle,
2478 argv[2],
2479 level,
2480 &buffer,
2481 offered,
2482 &info,
2483 &needed,
2484 &werror);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 werror = ntstatus_to_werror(status);
2487 goto done;
2491 if (!W_ERROR_IS_OK(werror)) {
2492 goto done;
2495 switch (level) {
2496 case 1:
2497 display_form_info1(&info.info1);
2498 break;
2499 case 2:
2500 display_form_info2(&info.info2);
2501 break;
2504 done:
2505 if (is_valid_policy_hnd(&handle)) {
2506 WERROR _result;
2507 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2510 return werror;
2513 /****************************************************************************
2514 ****************************************************************************/
2516 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2517 TALLOC_CTX *mem_ctx, int argc,
2518 const char **argv)
2520 struct policy_handle handle;
2521 WERROR werror;
2522 NTSTATUS status;
2523 const char *printername;
2524 struct dcerpc_binding_handle *b = cli->binding_handle;
2526 /* Parse the command arguments */
2528 if (argc != 3) {
2529 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2530 return WERR_OK;
2533 /* Get a printer handle */
2535 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2537 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2538 printername,
2539 SEC_FLAG_MAXIMUM_ALLOWED,
2540 &handle);
2541 if (!W_ERROR_IS_OK(werror))
2542 goto done;
2544 /* Delete the form */
2546 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2547 &handle,
2548 argv[2],
2549 &werror);
2550 if (!NT_STATUS_IS_OK(status)) {
2551 werror = ntstatus_to_werror(status);
2552 goto done;
2555 done:
2556 if (is_valid_policy_hnd(&handle)) {
2557 WERROR _result;
2558 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2561 return werror;
2564 /****************************************************************************
2565 ****************************************************************************/
2567 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2568 TALLOC_CTX *mem_ctx, int argc,
2569 const char **argv)
2571 struct policy_handle handle;
2572 WERROR werror;
2573 const char *printername;
2574 uint32_t num_forms, level = 1, i;
2575 union spoolss_FormInfo *forms;
2576 struct dcerpc_binding_handle *b = cli->binding_handle;
2578 /* Parse the command arguments */
2580 if (argc < 2 || argc > 4) {
2581 printf ("Usage: %s <printer> [level]\n", argv[0]);
2582 return WERR_OK;
2585 /* Get a printer handle */
2587 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2589 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2590 printername,
2591 SEC_FLAG_MAXIMUM_ALLOWED,
2592 &handle);
2593 if (!W_ERROR_IS_OK(werror))
2594 goto done;
2596 if (argc == 3) {
2597 level = atoi(argv[2]);
2600 /* Enumerate forms */
2602 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2603 &handle,
2604 level,
2606 &num_forms,
2607 &forms);
2609 if (!W_ERROR_IS_OK(werror))
2610 goto done;
2612 /* Display output */
2614 for (i = 0; i < num_forms; i++) {
2615 switch (level) {
2616 case 1:
2617 display_form_info1(&forms[i].info1);
2618 break;
2619 case 2:
2620 display_form_info2(&forms[i].info2);
2621 break;
2625 done:
2626 if (is_valid_policy_hnd(&handle)) {
2627 WERROR _result;
2628 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2631 return werror;
2634 /****************************************************************************
2635 ****************************************************************************/
2637 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2638 TALLOC_CTX *mem_ctx,
2639 int argc, const char **argv)
2641 WERROR result;
2642 NTSTATUS status;
2643 const char *printername;
2644 struct policy_handle pol = { 0, };
2645 union spoolss_PrinterInfo info;
2646 enum winreg_Type type;
2647 union spoolss_PrinterData data;
2648 DATA_BLOB blob;
2649 struct dcerpc_binding_handle *b = cli->binding_handle;
2650 int error = 0;
2652 /* parse the command arguments */
2653 if (argc < 5) {
2654 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2655 " <value> <data>\n",
2656 argv[0]);
2657 return WERR_OK;
2660 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2662 type = REG_NONE;
2664 if (strequal(argv[2], "string")) {
2665 type = REG_SZ;
2668 if (strequal(argv[2], "binary")) {
2669 type = REG_BINARY;
2672 if (strequal(argv[2], "dword")) {
2673 type = REG_DWORD;
2676 if (strequal(argv[2], "multistring")) {
2677 type = REG_MULTI_SZ;
2680 if (type == REG_NONE) {
2681 printf("Unknown data type: %s\n", argv[2]);
2682 result = WERR_INVALID_PARAMETER;
2683 goto done;
2686 /* get a printer handle */
2688 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2689 printername,
2690 SEC_FLAG_MAXIMUM_ALLOWED,
2691 &pol);
2692 if (!W_ERROR_IS_OK(result)) {
2693 goto done;
2696 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2697 &pol,
2700 &info);
2701 if (!W_ERROR_IS_OK(result)) {
2702 goto done;
2705 printf("%s\n", current_timestring(mem_ctx, true));
2706 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2708 /* Set the printer data */
2710 switch (type) {
2711 case REG_SZ:
2712 data.string = talloc_strdup(mem_ctx, argv[4]);
2713 W_ERROR_HAVE_NO_MEMORY(data.string);
2714 break;
2715 case REG_DWORD:
2716 data.value = smb_strtoul(argv[4],
2717 NULL,
2719 &error,
2720 SMB_STR_STANDARD);
2721 if (error != 0) {
2722 result = WERR_INVALID_PARAMETER;
2723 goto done;
2726 break;
2727 case REG_BINARY:
2728 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2729 break;
2730 case REG_MULTI_SZ: {
2731 int i;
2732 size_t num_strings;
2733 const char **strings = NULL;
2735 num_strings = 0;
2737 for (i=4; i<argc; i++) {
2738 if (strcmp(argv[i], "NULL") == 0) {
2739 argv[i] = "";
2741 if (!add_string_to_array(mem_ctx, argv[i],
2742 &strings,
2743 &num_strings)) {
2744 result = WERR_NOT_ENOUGH_MEMORY;
2745 goto done;
2748 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2749 if (!data.string_array) {
2750 result = WERR_NOT_ENOUGH_MEMORY;
2751 goto done;
2753 for (i=0; i < num_strings; i++) {
2754 data.string_array[i] = strings[i];
2756 break;
2758 default:
2759 printf("Unknown data type: %s\n", argv[2]);
2760 result = WERR_INVALID_PARAMETER;
2761 goto done;
2764 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2765 if (!W_ERROR_IS_OK(result)) {
2766 goto done;
2769 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2770 &pol,
2771 argv[3], /* value_name */
2772 type,
2773 blob.data,
2774 blob.length,
2775 &result);
2776 if (!NT_STATUS_IS_OK(status)) {
2777 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2778 result = ntstatus_to_werror(status);
2779 goto done;
2781 if (!W_ERROR_IS_OK(result)) {
2782 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2783 goto done;
2785 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2787 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2788 &pol,
2791 &info);
2792 if (!W_ERROR_IS_OK(result)) {
2793 goto done;
2796 printf("%s\n", current_timestring(mem_ctx, true));
2797 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2799 done:
2800 /* cleanup */
2801 if (is_valid_policy_hnd(&pol)) {
2802 WERROR _result;
2803 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2806 return result;
2809 /****************************************************************************
2810 ****************************************************************************/
2812 static void display_job_info1(struct spoolss_JobInfo1 *r)
2814 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2815 r->user_name, r->document_name, r->text_status, r->pages_printed,
2816 r->total_pages);
2819 /****************************************************************************
2820 ****************************************************************************/
2822 static void display_job_info2(struct spoolss_JobInfo2 *r)
2824 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2825 r->position, r->job_id,
2826 r->user_name, r->document_name, r->text_status, r->pages_printed,
2827 r->total_pages, r->size);
2830 /****************************************************************************
2831 ****************************************************************************/
2833 static void display_job_info3(struct spoolss_JobInfo3 *r)
2835 printf("jobid[%d], next_jobid[%d]\n",
2836 r->job_id, r->next_job_id);
2839 /****************************************************************************
2840 ****************************************************************************/
2842 static void display_job_info4(struct spoolss_JobInfo4 *r)
2844 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2845 r->position, r->job_id,
2846 r->user_name, r->document_name, r->text_status, r->pages_printed,
2847 r->total_pages, r->size, r->size_high);
2850 /****************************************************************************
2851 ****************************************************************************/
2853 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2854 TALLOC_CTX *mem_ctx, int argc,
2855 const char **argv)
2857 WERROR result;
2858 uint32_t level = 1, count, i;
2859 const char *printername;
2860 struct policy_handle hnd;
2861 union spoolss_JobInfo *info;
2862 struct dcerpc_binding_handle *b = cli->binding_handle;
2864 if (argc < 2 || argc > 3) {
2865 printf("Usage: %s printername [level]\n", argv[0]);
2866 return WERR_OK;
2869 if (argc == 3) {
2870 level = atoi(argv[2]);
2873 /* Open printer handle */
2875 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2877 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2878 printername,
2879 SEC_FLAG_MAXIMUM_ALLOWED,
2880 &hnd);
2881 if (!W_ERROR_IS_OK(result))
2882 goto done;
2884 /* Enumerate ports */
2886 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2887 &hnd,
2888 0, /* firstjob */
2889 1000, /* numjobs */
2890 level,
2892 &count,
2893 &info);
2894 if (!W_ERROR_IS_OK(result)) {
2895 goto done;
2898 for (i = 0; i < count; i++) {
2899 switch (level) {
2900 case 1:
2901 display_job_info1(&info[i].info1);
2902 break;
2903 case 2:
2904 display_job_info2(&info[i].info2);
2905 break;
2906 default:
2907 d_printf("unknown info level %d\n", level);
2908 break;
2912 done:
2913 if (is_valid_policy_hnd(&hnd)) {
2914 WERROR _result;
2915 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2918 return result;
2921 /****************************************************************************
2922 ****************************************************************************/
2924 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2925 TALLOC_CTX *mem_ctx, int argc,
2926 const char **argv)
2928 WERROR result;
2929 const char *printername;
2930 struct policy_handle hnd;
2931 uint32_t job_id;
2932 uint32_t level = 1;
2933 union spoolss_JobInfo info;
2934 struct dcerpc_binding_handle *b = cli->binding_handle;
2936 if (argc < 3 || argc > 4) {
2937 printf("Usage: %s printername job_id [level]\n", argv[0]);
2938 return WERR_OK;
2941 job_id = atoi(argv[2]);
2943 if (argc == 4) {
2944 level = atoi(argv[3]);
2947 /* Open printer handle */
2949 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2951 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2952 printername,
2953 SEC_FLAG_MAXIMUM_ALLOWED,
2954 &hnd);
2955 if (!W_ERROR_IS_OK(result)) {
2956 goto done;
2959 /* Enumerate ports */
2961 result = rpccli_spoolss_getjob(cli, mem_ctx,
2962 &hnd,
2963 job_id,
2964 level,
2966 &info);
2968 if (!W_ERROR_IS_OK(result)) {
2969 goto done;
2972 switch (level) {
2973 case 1:
2974 display_job_info1(&info.info1);
2975 break;
2976 case 2:
2977 display_job_info2(&info.info2);
2978 break;
2979 case 3:
2980 display_job_info3(&info.info3);
2981 break;
2982 case 4:
2983 display_job_info4(&info.info4);
2984 break;
2985 default:
2986 d_printf("unknown info level %d\n", level);
2987 break;
2990 done:
2991 if (is_valid_policy_hnd(&hnd)) {
2992 WERROR _result;
2993 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2996 return result;
2999 /****************************************************************************
3000 ****************************************************************************/
3002 static struct {
3003 const char *name;
3004 enum spoolss_JobControl val;
3005 } cmdvals[] = {
3006 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
3007 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
3008 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
3009 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
3010 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
3011 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
3012 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
3013 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
3014 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
3017 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
3019 int i;
3021 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
3022 if (strequal(cmdvals[i].name, cmd)) {
3023 return cmdvals[i].val;
3026 return (enum spoolss_JobControl)atoi(cmd);
3029 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
3030 TALLOC_CTX *mem_ctx, int argc,
3031 const char **argv)
3033 WERROR result;
3034 NTSTATUS status;
3035 const char *printername;
3036 struct policy_handle hnd;
3037 uint32_t job_id;
3038 enum spoolss_JobControl command;
3039 struct dcerpc_binding_handle *b = cli->binding_handle;
3041 if (argc != 4) {
3042 printf("Usage: %s printername job_id command\n", argv[0]);
3043 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3044 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3045 return WERR_OK;
3048 job_id = atoi(argv[2]);
3049 command = parse_setjob_command(argv[3]);
3051 /* Open printer handle */
3053 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3055 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3056 printername,
3057 SEC_FLAG_MAXIMUM_ALLOWED,
3058 &hnd);
3059 if (!W_ERROR_IS_OK(result)) {
3060 goto done;
3063 /* Set Job */
3065 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3066 &hnd,
3067 job_id,
3068 NULL,
3069 command,
3070 &result);
3071 if (!NT_STATUS_IS_OK(status)) {
3072 result = ntstatus_to_werror(status);
3073 goto done;
3075 if (!W_ERROR_IS_OK(result)) {
3076 goto done;
3079 done:
3080 if (is_valid_policy_hnd(&hnd)) {
3081 WERROR _result;
3082 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3085 return result;
3088 /****************************************************************************
3089 ****************************************************************************/
3091 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
3092 TALLOC_CTX *mem_ctx, int argc,
3093 const char **argv)
3095 WERROR result;
3096 NTSTATUS status;
3097 const char *printername;
3098 struct policy_handle hnd;
3099 uint32_t value_needed;
3100 enum winreg_Type type;
3101 uint32_t data_needed;
3102 struct dcerpc_binding_handle *b = cli->binding_handle;
3103 struct spoolss_EnumPrinterData r;
3105 if (argc != 2) {
3106 printf("Usage: %s printername\n", argv[0]);
3107 return WERR_OK;
3110 /* Open printer handle */
3112 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3114 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3115 printername,
3116 SEC_FLAG_MAXIMUM_ALLOWED,
3117 &hnd);
3118 if (!W_ERROR_IS_OK(result)) {
3119 goto done;
3122 /* Enumerate data */
3124 r.in.handle = &hnd;
3125 r.in.enum_index = 0;
3126 r.in.value_offered = 0;
3127 r.in.data_offered = 0;
3128 r.out.value_name = NULL;
3129 r.out.value_needed = &value_needed;
3130 r.out.type = &type;
3131 r.out.data = NULL;
3132 r.out.data_needed = &data_needed;
3134 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3135 if (!NT_STATUS_IS_OK(status)) {
3136 result = ntstatus_to_werror(status);
3137 goto done;
3140 if (!W_ERROR_IS_OK(r.out.result)) {
3141 result = r.out.result;
3142 goto done;
3145 r.in.data_offered = *r.out.data_needed;
3146 r.in.value_offered = *r.out.value_needed;
3147 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3148 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3150 do {
3152 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3153 if (!NT_STATUS_IS_OK(status)) {
3154 result = ntstatus_to_werror(status);
3155 goto done;
3158 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3159 result = WERR_OK;
3160 break;
3163 r.in.enum_index++;
3165 display_reg_value(r.out.value_name, *r.out.type,
3166 data_blob_const(r.out.data, r.in.data_offered));
3168 } while (W_ERROR_IS_OK(r.out.result));
3170 done:
3171 if (is_valid_policy_hnd(&hnd)) {
3172 WERROR _result;
3173 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3176 return result;
3179 /****************************************************************************
3180 ****************************************************************************/
3182 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3183 TALLOC_CTX *mem_ctx, int argc,
3184 const char **argv)
3186 WERROR result;
3187 uint32_t i;
3188 const char *printername;
3189 struct policy_handle hnd;
3190 uint32_t count;
3191 struct spoolss_PrinterEnumValues *info;
3192 struct dcerpc_binding_handle *b = cli->binding_handle;
3194 if (argc != 3) {
3195 printf("Usage: %s printername <keyname>\n", argv[0]);
3196 return WERR_OK;
3199 /* Open printer handle */
3201 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3203 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3204 printername,
3205 SEC_FLAG_MAXIMUM_ALLOWED,
3206 &hnd);
3207 if (!W_ERROR_IS_OK(result)) {
3208 goto done;
3211 /* Enumerate subkeys */
3213 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3214 &hnd,
3215 argv[2],
3217 &count,
3218 &info);
3219 if (!W_ERROR_IS_OK(result)) {
3220 goto done;
3223 for (i=0; i < count; i++) {
3224 display_printer_data(info[i].value_name,
3225 info[i].type,
3226 info[i].data->data,
3227 info[i].data->length);
3230 done:
3231 if (is_valid_policy_hnd(&hnd)) {
3232 WERROR _result;
3233 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3236 return result;
3239 /****************************************************************************
3240 ****************************************************************************/
3242 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3243 TALLOC_CTX *mem_ctx, int argc,
3244 const char **argv)
3246 WERROR result;
3247 const char *printername;
3248 const char *keyname = NULL;
3249 struct policy_handle hnd;
3250 const char **key_buffer = NULL;
3251 int i;
3252 uint32_t offered = 0;
3253 struct dcerpc_binding_handle *b = cli->binding_handle;
3255 if (argc < 2 || argc > 4) {
3256 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3257 return WERR_OK;
3260 if (argc >= 3) {
3261 keyname = argv[2];
3262 } else {
3263 keyname = "";
3266 if (argc == 4) {
3267 offered = atoi(argv[3]);
3270 /* Open printer handle */
3272 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3274 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3275 printername,
3276 SEC_FLAG_MAXIMUM_ALLOWED,
3277 &hnd);
3278 if (!W_ERROR_IS_OK(result)) {
3279 goto done;
3282 /* Enumerate subkeys */
3284 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3285 &hnd,
3286 keyname,
3287 &key_buffer,
3288 offered);
3290 if (!W_ERROR_IS_OK(result)) {
3291 goto done;
3294 for (i=0; key_buffer && key_buffer[i]; i++) {
3295 printf("%s\n", key_buffer[i]);
3298 done:
3300 if (is_valid_policy_hnd(&hnd)) {
3301 WERROR _result;
3302 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3305 return result;
3308 /****************************************************************************
3309 ****************************************************************************/
3311 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3312 TALLOC_CTX *mem_ctx, int argc,
3313 const char **argv)
3315 const char *printername;
3316 const char *clientname;
3317 struct policy_handle hnd = { 0, };
3318 WERROR result;
3319 NTSTATUS status;
3320 struct spoolss_NotifyOption option;
3321 struct dcerpc_binding_handle *b = cli->binding_handle;
3323 if (argc != 2) {
3324 printf("Usage: %s printername\n", argv[0]);
3325 result = WERR_OK;
3326 goto done;
3329 /* Open printer */
3331 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3333 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3334 printername,
3335 SEC_FLAG_MAXIMUM_ALLOWED,
3336 &hnd);
3337 if (!W_ERROR_IS_OK(result)) {
3338 printf("Error opening %s\n", argv[1]);
3339 goto done;
3342 /* Create spool options */
3344 option.version = 2;
3345 option.count = 2;
3347 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3348 if (option.types == NULL) {
3349 result = WERR_NOT_ENOUGH_MEMORY;
3350 goto done;
3353 option.types[0].type = PRINTER_NOTIFY_TYPE;
3354 option.types[0].count = 1;
3355 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3356 if (option.types[0].fields == NULL) {
3357 result = WERR_NOT_ENOUGH_MEMORY;
3358 goto done;
3360 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3362 option.types[1].type = JOB_NOTIFY_TYPE;
3363 option.types[1].count = 1;
3364 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3365 if (option.types[1].fields == NULL) {
3366 result = WERR_NOT_ENOUGH_MEMORY;
3367 goto done;
3369 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3371 clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3372 if (!clientname) {
3373 result = WERR_NOT_ENOUGH_MEMORY;
3374 goto done;
3377 /* Send rffpcnex */
3379 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3380 &hnd,
3383 clientname,
3384 123,
3385 &option,
3386 &result);
3387 if (!NT_STATUS_IS_OK(status)) {
3388 result = ntstatus_to_werror(status);
3389 goto done;
3391 if (!W_ERROR_IS_OK(result)) {
3392 printf("Error rffpcnex %s\n", argv[1]);
3393 goto done;
3396 done:
3397 if (is_valid_policy_hnd(&hnd)) {
3398 WERROR _result;
3399 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3402 return result;
3405 /****************************************************************************
3406 ****************************************************************************/
3408 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3409 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3411 union spoolss_PrinterInfo info1, info2;
3412 WERROR werror;
3413 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3415 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3416 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3417 hnd1,
3420 &info1);
3421 if ( !W_ERROR_IS_OK(werror) ) {
3422 printf("failed (%s)\n", win_errstr(werror));
3423 talloc_destroy(mem_ctx);
3424 return false;
3426 printf("ok\n");
3428 printf("Retrieving printer properties for %s...", cli2->desthost);
3429 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3430 hnd2,
3433 &info2);
3434 if ( !W_ERROR_IS_OK(werror) ) {
3435 printf("failed (%s)\n", win_errstr(werror));
3436 talloc_destroy(mem_ctx);
3437 return false;
3439 printf("ok\n");
3441 talloc_destroy(mem_ctx);
3443 return true;
3446 /****************************************************************************
3447 ****************************************************************************/
3449 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3450 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3452 union spoolss_PrinterInfo info1, info2;
3453 WERROR werror;
3454 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3455 struct security_descriptor *sd1, *sd2;
3456 bool result = true;
3459 printf("Retrieving printer security for %s...", cli1->desthost);
3460 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3461 hnd1,
3464 &info1);
3465 if ( !W_ERROR_IS_OK(werror) ) {
3466 printf("failed (%s)\n", win_errstr(werror));
3467 result = false;
3468 goto done;
3470 printf("ok\n");
3472 printf("Retrieving printer security for %s...", cli2->desthost);
3473 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3474 hnd2,
3477 &info2);
3478 if ( !W_ERROR_IS_OK(werror) ) {
3479 printf("failed (%s)\n", win_errstr(werror));
3480 result = false;
3481 goto done;
3483 printf("ok\n");
3486 printf("++ ");
3488 sd1 = info1.info3.secdesc;
3489 sd2 = info2.info3.secdesc;
3491 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3492 printf("NULL secdesc!\n");
3493 result = false;
3494 goto done;
3497 if (!security_descriptor_equal( sd1, sd2 ) ) {
3498 printf("Security Descriptors *not* equal!\n");
3499 result = false;
3500 goto done;
3503 printf("Security descriptors match\n");
3505 done:
3506 talloc_destroy(mem_ctx);
3507 return result;
3511 /****************************************************************************
3512 ****************************************************************************/
3514 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3515 TALLOC_CTX *mem_ctx, int argc,
3516 const char **argv)
3518 const char *printername;
3519 char *printername_path = NULL;
3520 struct cli_state *cli_server2 = NULL;
3521 struct rpc_pipe_client *cli2 = NULL;
3522 struct policy_handle hPrinter1, hPrinter2;
3523 NTSTATUS nt_status;
3524 WERROR werror;
3526 if ( argc != 3 ) {
3527 printf("Usage: %s <printer> <server>\n", argv[0]);
3528 return WERR_OK;
3531 printername = argv[1];
3533 /* first get the connection to the remote server */
3535 nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
3536 NULL, 0,
3537 "IPC$", "IPC",
3538 get_cmdline_auth_info_username(
3539 popt_get_cmdline_auth_info()),
3540 lp_workgroup(),
3541 get_cmdline_auth_info_password(
3542 popt_get_cmdline_auth_info()),
3543 get_cmdline_auth_info_use_kerberos(
3544 popt_get_cmdline_auth_info()) ?
3545 CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3546 get_cmdline_auth_info_signing_state(
3547 popt_get_cmdline_auth_info()));
3549 if ( !NT_STATUS_IS_OK(nt_status) )
3550 return WERR_GEN_FAILURE;
3552 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3553 &cli2);
3554 if (!NT_STATUS_IS_OK(nt_status)) {
3555 printf("failed to open spoolss pipe on server %s (%s)\n",
3556 argv[2], nt_errstr(nt_status));
3557 return WERR_GEN_FAILURE;
3560 /* now open up both printers */
3562 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3564 printf("Opening %s...", printername_path);
3566 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3567 printername_path,
3568 PRINTER_ALL_ACCESS,
3569 &hPrinter1);
3570 if ( !W_ERROR_IS_OK(werror) ) {
3571 printf("failed (%s)\n", win_errstr(werror));
3572 goto done;
3574 printf("ok\n");
3576 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3578 printf("Opening %s...", printername_path);
3579 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3580 printername_path,
3581 PRINTER_ALL_ACCESS,
3582 &hPrinter2);
3583 if ( !W_ERROR_IS_OK(werror) ) {
3584 printf("failed (%s)\n", win_errstr(werror));
3585 goto done;
3587 printf("ok\n");
3589 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3590 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3591 #if 0
3592 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3593 #endif
3596 done:
3597 /* cleanup */
3599 printf("Closing printers...");
3601 WERROR _result;
3602 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3603 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3605 printf("ok\n");
3607 /* close the second remote connection */
3609 cli_shutdown( cli_server2 );
3610 return WERR_OK;
3613 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3615 printf("print_processor_name: %s\n", r->print_processor_name);
3618 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3619 TALLOC_CTX *mem_ctx, int argc,
3620 const char **argv)
3622 WERROR werror;
3623 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3624 uint32_t num_procs, level = 1, i;
3625 union spoolss_PrintProcessorInfo *procs;
3627 /* Parse the command arguments */
3629 if (argc < 1 || argc > 4) {
3630 printf ("Usage: %s [environment] [level]\n", argv[0]);
3631 return WERR_OK;
3634 if (argc >= 2) {
3635 environment = argv[1];
3638 if (argc == 3) {
3639 level = atoi(argv[2]);
3642 /* Enumerate Print Processors */
3644 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3645 cli->srv_name_slash,
3646 environment,
3647 level,
3649 &num_procs,
3650 &procs);
3651 if (!W_ERROR_IS_OK(werror))
3652 goto done;
3654 /* Display output */
3656 for (i = 0; i < num_procs; i++) {
3657 switch (level) {
3658 case 1:
3659 display_proc_info1(&procs[i].info1);
3660 break;
3664 done:
3665 return werror;
3668 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3670 printf("name_array: %s\n", r->name_array);
3673 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3674 TALLOC_CTX *mem_ctx, int argc,
3675 const char **argv)
3677 WERROR werror;
3678 const char *print_processor_name = "winprint";
3679 uint32_t num_procs, level = 1, i;
3680 union spoolss_PrintProcDataTypesInfo *procs;
3682 /* Parse the command arguments */
3684 if (argc < 1 || argc > 4) {
3685 printf ("Usage: %s [environment] [level]\n", argv[0]);
3686 return WERR_OK;
3689 if (argc >= 2) {
3690 print_processor_name = argv[1];
3693 if (argc == 3) {
3694 level = atoi(argv[2]);
3697 /* Enumerate Print Processor Data Types */
3699 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3700 cli->srv_name_slash,
3701 print_processor_name,
3702 level,
3704 &num_procs,
3705 &procs);
3706 if (!W_ERROR_IS_OK(werror))
3707 goto done;
3709 /* Display output */
3711 for (i = 0; i < num_procs; i++) {
3712 switch (level) {
3713 case 1:
3714 display_proc_data_types_info1(&procs[i].info1);
3715 break;
3719 done:
3720 return werror;
3723 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3725 printf("monitor_name: %s\n", r->monitor_name);
3728 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3730 printf("monitor_name: %s\n", r->monitor_name);
3731 printf("environment: %s\n", r->environment);
3732 printf("dll_name: %s\n", r->dll_name);
3735 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3736 TALLOC_CTX *mem_ctx, int argc,
3737 const char **argv)
3739 WERROR werror;
3740 uint32_t count, level = 1, i;
3741 union spoolss_MonitorInfo *info;
3743 /* Parse the command arguments */
3745 if (argc > 2) {
3746 printf("Usage: %s [level]\n", argv[0]);
3747 return WERR_OK;
3750 if (argc == 2) {
3751 level = atoi(argv[1]);
3754 /* Enumerate Print Monitors */
3756 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3757 cli->srv_name_slash,
3758 level,
3760 &count,
3761 &info);
3762 if (!W_ERROR_IS_OK(werror)) {
3763 goto done;
3766 /* Display output */
3768 for (i = 0; i < count; i++) {
3769 switch (level) {
3770 case 1:
3771 display_monitor1(&info[i].info1);
3772 break;
3773 case 2:
3774 display_monitor2(&info[i].info2);
3775 break;
3779 done:
3780 return werror;
3783 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3784 TALLOC_CTX *mem_ctx, int argc,
3785 const char **argv)
3787 WERROR result;
3788 NTSTATUS status;
3789 struct policy_handle handle, gdi_handle;
3790 const char *printername;
3791 struct spoolss_DevmodeContainer devmode_ctr;
3792 struct dcerpc_binding_handle *b = cli->binding_handle;
3794 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3796 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3797 printername,
3798 SEC_FLAG_MAXIMUM_ALLOWED,
3799 &handle);
3800 if (!W_ERROR_IS_OK(result)) {
3801 return result;
3804 ZERO_STRUCT(devmode_ctr);
3806 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3807 &handle,
3808 &gdi_handle,
3809 &devmode_ctr,
3810 &result);
3811 if (!NT_STATUS_IS_OK(status)) {
3812 result = ntstatus_to_werror(status);
3813 goto done;
3815 if (!W_ERROR_IS_OK(result)) {
3816 goto done;
3819 done:
3820 if (is_valid_policy_hnd(&gdi_handle)) {
3821 WERROR _result;
3822 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3824 if (is_valid_policy_hnd(&handle)) {
3825 WERROR _result;
3826 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3829 return result;
3832 static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3833 TALLOC_CTX *mem_ctx, int argc,
3834 const char **argv)
3836 WERROR result;
3837 NTSTATUS status;
3838 struct policy_handle handle, gdi_handle;
3839 const char *printername;
3840 struct spoolss_DevmodeContainer devmode_ctr;
3841 struct dcerpc_binding_handle *b = cli->binding_handle;
3842 DATA_BLOB in,out;
3843 uint32_t count = 0;
3845 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3847 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3848 printername,
3849 SEC_FLAG_MAXIMUM_ALLOWED,
3850 &handle);
3851 if (!W_ERROR_IS_OK(result)) {
3852 return result;
3855 ZERO_STRUCT(devmode_ctr);
3857 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3858 &handle,
3859 &gdi_handle,
3860 &devmode_ctr,
3861 &result);
3862 if (!NT_STATUS_IS_OK(status)) {
3863 result = ntstatus_to_werror(status);
3864 goto done;
3866 if (!W_ERROR_IS_OK(result)) {
3867 goto done;
3870 in = data_blob_string_const("");
3871 out = data_blob_talloc_zero(mem_ctx, 4);
3873 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3874 &gdi_handle,
3875 in.data,
3876 in.length,
3877 out.data,
3878 out.length,
3879 0, /* ul */
3880 &result);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 result = ntstatus_to_werror(status);
3883 goto done;
3885 if (!W_ERROR_IS_OK(result)) {
3886 goto done;
3889 count = IVAL(out.data, 0);
3891 out = data_blob_talloc_zero(mem_ctx,
3892 count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3894 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3895 &gdi_handle,
3896 in.data,
3897 in.length,
3898 out.data,
3899 out.length,
3900 0, /* ul */
3901 &result);
3902 if (!NT_STATUS_IS_OK(status)) {
3903 result = ntstatus_to_werror(status);
3904 goto done;
3906 if (!W_ERROR_IS_OK(result)) {
3907 goto done;
3911 enum ndr_err_code ndr_err;
3912 struct UNIVERSAL_FONT_ID_ctr r;
3914 ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3915 (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3916 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3917 NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3921 done:
3922 if (is_valid_policy_hnd(&gdi_handle)) {
3923 WERROR _result;
3924 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3926 if (is_valid_policy_hnd(&handle)) {
3927 WERROR _result;
3928 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3931 return result;
3934 static WERROR cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client *cli,
3935 TALLOC_CTX *mem_ctx, int argc,
3936 const char **argv)
3938 NTSTATUS status;
3939 HRESULT result;
3940 struct dcerpc_binding_handle *b = cli->binding_handle;
3941 const char *architecture = SPOOLSS_ARCHITECTURE_x64;
3942 struct spoolss_CorePrinterDriver core_printer_drivers;
3943 DATA_BLOB blob;
3944 bool ok;
3945 int i;
3946 uint32_t count;
3947 const char **array;
3949 if (argc == 1) {
3950 count = 1;
3951 array = talloc_zero_array(mem_ctx, const char *, count + 1);
3952 if (array == NULL) {
3953 return WERR_NOT_ENOUGH_MEMORY;
3955 array[0] = talloc_strdup(array, SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
3956 if (array[0] == NULL) {
3957 return WERR_NOT_ENOUGH_MEMORY;
3959 } else {
3960 count = argc -1;
3961 array = talloc_zero_array(mem_ctx, const char *, count + 1);
3962 if (array == NULL) {
3963 return WERR_NOT_ENOUGH_MEMORY;
3965 for (i = 0; i < argc - 1; i++) {
3966 array[i] = talloc_strdup(array, argv[i + 1]);
3967 if (array[i] == NULL) {
3968 return WERR_NOT_ENOUGH_MEMORY;
3973 ok = push_reg_multi_sz(mem_ctx, &blob, array);
3974 if (!ok) {
3975 return WERR_NOT_ENOUGH_MEMORY;
3978 status = dcerpc_spoolss_GetCorePrinterDrivers(b, mem_ctx,
3979 cli->srv_name_slash,
3980 architecture,
3981 blob.length/2,
3982 (uint16_t *)blob.data,
3983 count,
3984 &core_printer_drivers,
3985 &result);
3986 if (!NT_STATUS_IS_OK(status)) {
3987 return ntstatus_to_werror(status);
3990 if (!HRES_IS_OK(result)) {
3991 return W_ERROR(WIN32_FROM_HRESULT(result));
3994 return WERR_OK;
3997 static WERROR cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client *cli,
3998 TALLOC_CTX *mem_ctx, int argc,
3999 const char **argv)
4001 NTSTATUS status;
4002 WERROR result;
4003 struct dcerpc_binding_handle *b = cli->binding_handle;
4004 const char *servername = cli->srv_name_slash;
4005 DATA_BLOB in = data_blob_null;
4006 DATA_BLOB out = data_blob_null;
4007 uint32_t needed, count;
4009 if (argc > 2) {
4010 printf("usage: %s [servername]\n", argv[0]);
4011 return WERR_OK;
4014 if (argc > 1) {
4015 servername = argv[1];
4018 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4019 servername,
4020 &in,
4021 in.length,
4022 &out,
4023 &needed,
4024 &count,
4025 &result);
4026 if (!NT_STATUS_IS_OK(status)) {
4027 return ntstatus_to_werror(status);
4030 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
4031 in = data_blob_talloc_zero(mem_ctx, needed);
4032 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4033 servername,
4034 &in,
4035 in.length,
4036 &out,
4037 &needed,
4038 &count,
4039 &result);
4040 if (!NT_STATUS_IS_OK(status)) {
4041 return ntstatus_to_werror(status);
4045 return result;
4048 static WERROR cmd_spoolss_add_permachineconnection(struct rpc_pipe_client *cli,
4049 TALLOC_CTX *mem_ctx, int argc,
4050 const char **argv)
4052 NTSTATUS status;
4053 WERROR result;
4054 struct dcerpc_binding_handle *b = cli->binding_handle;
4055 const char *servername = cli->srv_name_slash;
4056 const char *printername = "Microsoft Print to PDF";
4057 const char *printserver = "samba.org";
4058 const char *provider = ""; /* refers to Win32spl.dll then */
4059 const char *composed_printername;
4061 if (argc > 5) {
4062 printf("usage: %s [servername] [printername] [printserver] [provider]\n", argv[0]);
4063 return WERR_OK;
4066 if (argc > 1) {
4067 servername = argv[1];
4069 if (argc > 2) {
4070 printername = argv[2];
4072 if (argc > 3) {
4073 printserver = argv[3];
4075 if (argc > 4) {
4076 provider = argv[4];
4079 composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4080 printername);
4081 if (composed_printername == NULL) {
4082 return WERR_NOT_ENOUGH_MEMORY;
4084 status = dcerpc_spoolss_AddPerMachineConnection(b, mem_ctx,
4085 servername,
4086 composed_printername,
4087 printserver,
4088 provider,
4089 &result);
4090 if (!NT_STATUS_IS_OK(status)) {
4091 return ntstatus_to_werror(status);
4094 return result;
4097 static WERROR cmd_spoolss_del_permachineconnection(struct rpc_pipe_client *cli,
4098 TALLOC_CTX *mem_ctx, int argc,
4099 const char **argv)
4101 NTSTATUS status;
4102 WERROR result;
4103 struct dcerpc_binding_handle *b = cli->binding_handle;
4104 const char *servername = cli->srv_name_slash;
4105 const char *printername = "Microsoft Print to PDF";
4106 const char *composed_printername;
4108 if (argc > 3) {
4109 printf("usage: %s [servername] [printername]\n", argv[0]);
4110 return WERR_OK;
4113 if (argc > 1) {
4114 servername = argv[1];
4116 if (argc > 2) {
4117 printername = argv[2];
4120 composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4121 printername);
4122 if (composed_printername == NULL) {
4123 return WERR_NOT_ENOUGH_MEMORY;
4126 status = dcerpc_spoolss_DeletePerMachineConnection(b, mem_ctx,
4127 servername,
4128 composed_printername,
4129 &result);
4130 if (!NT_STATUS_IS_OK(status)) {
4131 return ntstatus_to_werror(status);
4134 return result;
4137 /* List of commands exported by this module */
4138 struct cmd_set spoolss_commands[] = {
4141 .name = "SPOOLSS",
4145 .name = "adddriver",
4146 .returntype = RPC_RTYPE_WERROR,
4147 .ntfn = NULL,
4148 .wfn = cmd_spoolss_addprinterdriver,
4149 .table = &ndr_table_spoolss,
4150 .rpc_pipe = NULL,
4151 .description = "Add a print driver",
4152 .usage = "",
4153 .use_netlogon_creds = false,
4156 .name = "addprinter",
4157 .returntype = RPC_RTYPE_WERROR,
4158 .ntfn = NULL,
4159 .wfn = cmd_spoolss_addprinterex,
4160 .table = &ndr_table_spoolss,
4161 .rpc_pipe = NULL,
4162 .description = "Add a printer",
4163 .usage = "",
4166 .name = "deldriver",
4167 .returntype = RPC_RTYPE_WERROR,
4168 .ntfn = NULL,
4169 .wfn = cmd_spoolss_deletedriver,
4170 .table = &ndr_table_spoolss,
4171 .rpc_pipe = NULL,
4172 .description = "Delete a printer driver",
4173 .usage = "",
4176 .name = "deldriverex",
4177 .returntype = RPC_RTYPE_WERROR,
4178 .ntfn = NULL,
4179 .wfn = cmd_spoolss_deletedriverex,
4180 .table = &ndr_table_spoolss,
4181 .rpc_pipe = NULL,
4182 .description = "Delete a printer driver with files",
4183 .usage = "",
4186 .name = "enumdata",
4187 .returntype = RPC_RTYPE_WERROR,
4188 .ntfn = NULL,
4189 .wfn = cmd_spoolss_enum_data,
4190 .table = &ndr_table_spoolss,
4191 .rpc_pipe = NULL,
4192 .description = "Enumerate printer data",
4193 .usage = "",
4196 .name = "enumdataex",
4197 .returntype = RPC_RTYPE_WERROR,
4198 .ntfn = NULL,
4199 .wfn = cmd_spoolss_enum_data_ex,
4200 .table = &ndr_table_spoolss,
4201 .rpc_pipe = NULL,
4202 .description = "Enumerate printer data for a key",
4203 .usage = "",
4206 .name = "enumkey",
4207 .returntype = RPC_RTYPE_WERROR,
4208 .ntfn = NULL,
4209 .wfn = cmd_spoolss_enum_printerkey,
4210 .table = &ndr_table_spoolss,
4211 .rpc_pipe = NULL,
4212 .description = "Enumerate printer keys",
4213 .usage = "",
4216 .name = "enumjobs",
4217 .returntype = RPC_RTYPE_WERROR,
4218 .ntfn = NULL,
4219 .wfn = cmd_spoolss_enum_jobs,
4220 .table = &ndr_table_spoolss,
4221 .rpc_pipe = NULL,
4222 .description = "Enumerate print jobs",
4223 .usage = "",
4226 .name = "getjob",
4227 .returntype = RPC_RTYPE_WERROR,
4228 .ntfn = NULL,
4229 .wfn = cmd_spoolss_get_job,
4230 .table = &ndr_table_spoolss,
4231 .rpc_pipe = NULL,
4232 .description = "Get print job",
4233 .usage = "",
4236 .name = "setjob",
4237 .returntype = RPC_RTYPE_WERROR,
4238 .ntfn = NULL,
4239 .wfn = cmd_spoolss_set_job,
4240 .table = &ndr_table_spoolss,
4241 .rpc_pipe = NULL,
4242 .description = "Set print job",
4243 .usage = "",
4246 .name = "enumports",
4247 .returntype = RPC_RTYPE_WERROR,
4248 .ntfn = NULL,
4249 .wfn = cmd_spoolss_enum_ports,
4250 .table = &ndr_table_spoolss,
4251 .rpc_pipe = NULL,
4252 .description = "Enumerate printer ports",
4253 .usage = "",
4256 .name = "enumdrivers",
4257 .returntype = RPC_RTYPE_WERROR,
4258 .ntfn = NULL,
4259 .wfn = cmd_spoolss_enum_drivers,
4260 .table = &ndr_table_spoolss,
4261 .rpc_pipe = NULL,
4262 .description = "Enumerate installed printer drivers",
4263 .usage = "",
4266 .name = "enumprinters",
4267 .returntype = RPC_RTYPE_WERROR,
4268 .ntfn = NULL,
4269 .wfn = cmd_spoolss_enum_printers,
4270 .table = &ndr_table_spoolss,
4271 .rpc_pipe = NULL,
4272 .description = "Enumerate printers",
4273 .usage = "",
4276 .name = "getdata",
4277 .returntype = RPC_RTYPE_WERROR,
4278 .ntfn = NULL,
4279 .wfn = cmd_spoolss_getprinterdata,
4280 .table = &ndr_table_spoolss,
4281 .rpc_pipe = NULL,
4282 .description = "Get print driver data",
4283 .usage = "",
4286 .name = "getdataex",
4287 .returntype = RPC_RTYPE_WERROR,
4288 .ntfn = NULL,
4289 .wfn = cmd_spoolss_getprinterdataex,
4290 .table = &ndr_table_spoolss,
4291 .rpc_pipe = NULL,
4292 .description = "Get printer driver data with keyname",
4293 .usage = "",
4296 .name = "getdriver",
4297 .returntype = RPC_RTYPE_WERROR,
4298 .ntfn = NULL,
4299 .wfn = cmd_spoolss_getdriver,
4300 .table = &ndr_table_spoolss,
4301 .rpc_pipe = NULL,
4302 .description = "Get print driver information",
4303 .usage = "",
4306 .name = "getdriverdir",
4307 .returntype = RPC_RTYPE_WERROR,
4308 .ntfn = NULL,
4309 .wfn = cmd_spoolss_getdriverdir,
4310 .table = &ndr_table_spoolss,
4311 .rpc_pipe = NULL,
4312 .description = "Get print driver upload directory",
4313 .usage = "",
4316 .name = "getdriverpackagepath",
4317 .returntype = RPC_RTYPE_WERROR,
4318 .ntfn = NULL,
4319 .wfn = cmd_spoolss_getdriverpackagepath,
4320 .table = &ndr_table_spoolss,
4321 .rpc_pipe = NULL,
4322 .description = "Get print driver package download directory",
4323 .usage = "",
4326 .name = "getprinter",
4327 .returntype = RPC_RTYPE_WERROR,
4328 .ntfn = NULL,
4329 .wfn = cmd_spoolss_getprinter,
4330 .table = &ndr_table_spoolss,
4331 .rpc_pipe = NULL,
4332 .description = "Get printer info",
4333 .usage = "",
4336 .name = "openprinter",
4337 .returntype = RPC_RTYPE_WERROR,
4338 .ntfn = NULL,
4339 .wfn = cmd_spoolss_open_printer,
4340 .table = &ndr_table_spoolss,
4341 .rpc_pipe = NULL,
4342 .description = "Open printer handle",
4343 .usage = "",
4346 .name = "openprinter_ex",
4347 .returntype = RPC_RTYPE_WERROR,
4348 .ntfn = NULL,
4349 .wfn = cmd_spoolss_open_printer_ex,
4350 .table = &ndr_table_spoolss,
4351 .rpc_pipe = NULL,
4352 .description = "Open printer handle",
4353 .usage = "",
4356 .name = "setdriver",
4357 .returntype = RPC_RTYPE_WERROR,
4358 .ntfn = NULL,
4359 .wfn = cmd_spoolss_setdriver,
4360 .table = &ndr_table_spoolss,
4361 .rpc_pipe = NULL,
4362 .description = "Set printer driver",
4363 .usage = "",
4366 .name = "getprintprocdir",
4367 .returntype = RPC_RTYPE_WERROR,
4368 .ntfn = NULL,
4369 .wfn = cmd_spoolss_getprintprocdir,
4370 .table = &ndr_table_spoolss,
4371 .rpc_pipe = NULL,
4372 .description = "Get print processor directory",
4373 .usage = "",
4376 .name = "addform",
4377 .returntype = RPC_RTYPE_WERROR,
4378 .ntfn = NULL,
4379 .wfn = cmd_spoolss_addform,
4380 .table = &ndr_table_spoolss,
4381 .rpc_pipe = NULL,
4382 .description = "Add form",
4383 .usage = "",
4386 .name = "setform",
4387 .returntype = RPC_RTYPE_WERROR,
4388 .ntfn = NULL,
4389 .wfn = cmd_spoolss_setform,
4390 .table = &ndr_table_spoolss,
4391 .rpc_pipe = NULL,
4392 .description = "Set form",
4393 .usage = "",
4396 .name = "getform",
4397 .returntype = RPC_RTYPE_WERROR,
4398 .ntfn = NULL,
4399 .wfn = cmd_spoolss_getform,
4400 .table = &ndr_table_spoolss,
4401 .rpc_pipe = NULL,
4402 .description = "Get form",
4403 .usage = "",
4406 .name = "deleteform",
4407 .returntype = RPC_RTYPE_WERROR,
4408 .ntfn = NULL,
4409 .wfn = cmd_spoolss_deleteform,
4410 .table = &ndr_table_spoolss,
4411 .rpc_pipe = NULL,
4412 .description = "Delete form",
4413 .usage = "",
4416 .name = "enumforms",
4417 .returntype = RPC_RTYPE_WERROR,
4418 .ntfn = NULL,
4419 .wfn = cmd_spoolss_enum_forms,
4420 .table = &ndr_table_spoolss,
4421 .rpc_pipe = NULL,
4422 .description = "Enumerate forms",
4423 .usage = "",
4426 .name = "setprinter",
4427 .returntype = RPC_RTYPE_WERROR,
4428 .ntfn = NULL,
4429 .wfn = cmd_spoolss_setprinter,
4430 .table = &ndr_table_spoolss,
4431 .rpc_pipe = NULL,
4432 .description = "Set printer comment",
4433 .usage = "",
4436 .name = "setprintername",
4437 .returntype = RPC_RTYPE_WERROR,
4438 .ntfn = NULL,
4439 .wfn = cmd_spoolss_setprintername,
4440 .table = &ndr_table_spoolss,
4441 .rpc_pipe = NULL,
4442 .description = "Set printername",
4443 .usage = "",
4446 .name = "setprinterdata",
4447 .returntype = RPC_RTYPE_WERROR,
4448 .ntfn = NULL,
4449 .wfn = cmd_spoolss_setprinterdata,
4450 .table = &ndr_table_spoolss,
4451 .rpc_pipe = NULL,
4452 .description = "Set REG_SZ printer data",
4453 .usage = "",
4456 .name = "rffpcnex",
4457 .returntype = RPC_RTYPE_WERROR,
4458 .ntfn = NULL,
4459 .wfn = cmd_spoolss_rffpcnex,
4460 .table = &ndr_table_spoolss,
4461 .rpc_pipe = NULL,
4462 .description = "Rffpcnex test",
4463 .usage = "",
4466 .name = "printercmp",
4467 .returntype = RPC_RTYPE_WERROR,
4468 .ntfn = NULL,
4469 .wfn = cmd_spoolss_printercmp,
4470 .table = &ndr_table_spoolss,
4471 .rpc_pipe = NULL,
4472 .description = "Printer comparison test",
4473 .usage = "",
4476 .name = "enumprocs",
4477 .returntype = RPC_RTYPE_WERROR,
4478 .ntfn = NULL,
4479 .wfn = cmd_spoolss_enum_procs,
4480 .table = &ndr_table_spoolss,
4481 .rpc_pipe = NULL,
4482 .description = "Enumerate Print Processors",
4483 .usage = "",
4486 .name = "enumprocdatatypes",
4487 .returntype = RPC_RTYPE_WERROR,
4488 .ntfn = NULL,
4489 .wfn = cmd_spoolss_enum_proc_data_types,
4490 .table = &ndr_table_spoolss,
4491 .rpc_pipe = NULL,
4492 .description = "Enumerate Print Processor Data Types",
4493 .usage = "",
4496 .name = "enummonitors",
4497 .returntype = RPC_RTYPE_WERROR,
4498 .ntfn = NULL,
4499 .wfn = cmd_spoolss_enum_monitors,
4500 .table = &ndr_table_spoolss,
4501 .rpc_pipe = NULL,
4502 .description = "Enumerate Print Monitors",
4503 .usage = "",
4506 .name = "createprinteric",
4507 .returntype = RPC_RTYPE_WERROR,
4508 .ntfn = NULL,
4509 .wfn = cmd_spoolss_create_printer_ic,
4510 .table = &ndr_table_spoolss,
4511 .rpc_pipe = NULL,
4512 .description = "Create Printer IC",
4513 .usage = "",
4516 .name = "playgdiscriptonprinteric",
4517 .returntype = RPC_RTYPE_WERROR,
4518 .ntfn = NULL,
4519 .wfn = cmd_spoolss_play_gdi_script_on_printer_ic,
4520 .table = &ndr_table_spoolss,
4521 .rpc_pipe = NULL,
4522 .description = "Create Printer IC",
4523 .usage = "",
4526 .name = "getcoreprinterdrivers",
4527 .returntype = RPC_RTYPE_WERROR,
4528 .ntfn = NULL,
4529 .wfn = cmd_spoolss_get_core_printer_drivers,
4530 .table = &ndr_table_spoolss,
4531 .rpc_pipe = NULL,
4532 .description = "Get CorePrinterDriver",
4533 .usage = "",
4536 .name = "enumpermachineconnections",
4537 .returntype = RPC_RTYPE_WERROR,
4538 .ntfn = NULL,
4539 .wfn = cmd_spoolss_enum_permachineconnections,
4540 .table = &ndr_table_spoolss,
4541 .rpc_pipe = NULL,
4542 .description = "Enumerate Per Machine Connections",
4543 .usage = "",
4546 .name = "addpermachineconnection",
4547 .returntype = RPC_RTYPE_WERROR,
4548 .ntfn = NULL,
4549 .wfn = cmd_spoolss_add_permachineconnection,
4550 .table = &ndr_table_spoolss,
4551 .rpc_pipe = NULL,
4552 .description = "Add Per Machine Connection",
4553 .usage = "",
4556 .name = "delpermachineconnection",
4557 .returntype = RPC_RTYPE_WERROR,
4558 .ntfn = NULL,
4559 .wfn = cmd_spoolss_del_permachineconnection,
4560 .table = &ndr_table_spoolss,
4561 .rpc_pipe = NULL,
4562 .description = "Delete Per Machine Connection",
4563 .usage = "",
4566 .name = NULL,