lib:torture: add torture_assert_u32_[not_]equal[_goto] macros
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blob78c381b9a594a23498e98852119c13b92a4306dd
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_array(mem_ctx, char, offered);
1634 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1635 cli->srv_name_slash,
1636 env,
1637 NULL,
1638 package_id,
1639 cab,
1640 offered,
1641 &needed,
1642 &hresult);
1643 if (!NT_STATUS_IS_OK(status)) {
1644 return ntstatus_to_werror(status);
1647 if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
1648 offered = needed;
1649 cab = talloc_zero_array(mem_ctx, char, offered);
1651 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1652 cli->srv_name_slash,
1653 env,
1654 NULL,
1655 package_id,
1656 cab,
1657 offered,
1658 &needed,
1659 &hresult);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 return ntstatus_to_werror(status);
1665 return W_ERROR(WIN32_FROM_HRESULT(hresult));
1669 /****************************************************************************
1670 ****************************************************************************/
1672 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1673 struct spoolss_AddDriverInfo3 *info,
1674 const char *arch)
1677 int i;
1679 for (i=0; archi_table[i].long_archi != NULL; i++)
1681 if (strcmp(arch, archi_table[i].short_archi) == 0)
1683 info->version = archi_table[i].version;
1684 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1685 break;
1689 if (archi_table[i].long_archi == NULL)
1691 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1694 return;
1698 /**************************************************************************
1699 wrapper for strtok to get the next parameter from a delimited list.
1700 Needed to handle the empty parameter string denoted by "NULL"
1701 *************************************************************************/
1703 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1704 const char *delim, const char **dest,
1705 char **saveptr)
1707 char *ptr;
1709 /* get the next token */
1710 ptr = strtok_r(str, delim, saveptr);
1712 /* a string of 'NULL' is used to represent an empty
1713 parameter because two consecutive delimiters
1714 will not return an empty string. See man strtok(3)
1715 for details */
1716 if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1717 ptr = NULL;
1720 if (dest != NULL) {
1721 *dest = talloc_strdup(mem_ctx, ptr);
1724 return ptr;
1727 /********************************************************************************
1728 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1729 string in the form of
1730 <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1731 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1732 <Default Data Type>:<Comma Separated list of Files>
1733 *******************************************************************************/
1735 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1736 char *args)
1738 char *str, *str2;
1739 size_t count = 0;
1740 char *saveptr = NULL;
1741 struct spoolss_StringArray *deps;
1742 const char **file_array = NULL;
1743 int i;
1745 /* fill in the UNISTR fields */
1746 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1747 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1748 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1749 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1750 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1751 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1752 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1754 /* <Comma Separated List of Dependent Files> */
1755 /* save the beginning of the string */
1756 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1757 str = str2;
1759 /* begin to strip out each filename */
1760 str = strtok_r(str, ",", &saveptr);
1762 /* no dependent files, we are done */
1763 if (!str) {
1764 return true;
1767 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1768 if (!deps) {
1769 return false;
1772 while (str != NULL) {
1773 bool ok;
1774 ok = add_string_to_array(deps, str, &file_array, &count);
1775 if (!ok) {
1776 return false;
1778 str = strtok_r(NULL, ",", &saveptr);
1781 deps->string = talloc_zero_array(deps, const char *, count + 1);
1782 if (!deps->string) {
1783 return false;
1786 for (i=0; i < count; i++) {
1787 deps->string[i] = file_array[i];
1790 r->dependent_files = deps;
1792 return true;
1795 /****************************************************************************
1796 ****************************************************************************/
1798 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1799 TALLOC_CTX *mem_ctx,
1800 int argc, const char **argv)
1802 WERROR result;
1803 NTSTATUS status;
1804 uint32_t level = 3;
1805 struct spoolss_AddDriverInfoCtr info_ctr;
1806 struct spoolss_AddDriverInfo3 info3;
1807 const char *arch;
1808 char *driver_args;
1809 struct dcerpc_binding_handle *b = cli->binding_handle;
1811 /* parse the command arguments */
1812 if (argc != 3 && argc != 4)
1814 printf ("Usage: %s <Environment> \\\n", argv[0]);
1815 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1816 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1817 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1818 printf ("\t[version]\n");
1820 return WERR_OK;
1823 /* Fill in the spoolss_AddDriverInfo3 struct */
1824 ZERO_STRUCT(info3);
1826 arch = cmd_spoolss_get_short_archi(argv[1]);
1827 if (!arch) {
1828 printf ("Error Unknown architecture [%s]\n", argv[1]);
1829 return WERR_INVALID_PARAMETER;
1832 set_drv_info_3_env(mem_ctx, &info3, arch);
1834 driver_args = talloc_strdup( mem_ctx, argv[2] );
1835 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1837 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1838 return WERR_INVALID_PARAMETER;
1841 /* if printer driver version specified, override the default version
1842 * used by the architecture. This allows installation of Windows
1843 * 2000 (version 3) printer drivers. */
1844 if (argc == 4)
1846 info3.version = atoi(argv[3]);
1850 info_ctr.level = level;
1851 info_ctr.info.info3 = &info3;
1853 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1854 cli->srv_name_slash,
1855 &info_ctr,
1856 &result);
1857 if (!NT_STATUS_IS_OK(status)) {
1858 return ntstatus_to_werror(status);
1860 if (W_ERROR_IS_OK(result)) {
1861 printf ("Printer Driver %s successfully installed.\n",
1862 info3.driver_name);
1865 return result;
1869 /****************************************************************************
1870 ****************************************************************************/
1872 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1873 TALLOC_CTX *mem_ctx,
1874 int argc, const char **argv)
1876 WERROR result;
1877 struct spoolss_SetPrinterInfoCtr info_ctr;
1878 struct spoolss_SetPrinterInfo2 info2;
1880 /* parse the command arguments */
1881 if (argc != 5)
1883 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1884 return WERR_OK;
1887 /* Fill in the DRIVER_INFO_2 struct */
1888 ZERO_STRUCT(info2);
1890 info2.printername = argv[1];
1891 info2.drivername = argv[3];
1892 info2.sharename = argv[2];
1893 info2.portname = argv[4];
1894 info2.comment = "Created by rpcclient";
1895 info2.printprocessor = "winprint";
1896 info2.datatype = "RAW";
1897 info2.devmode_ptr = 0;
1898 info2.secdesc_ptr = 0;
1899 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1900 info2.priority = 0;
1901 info2.defaultpriority = 0;
1902 info2.starttime = 0;
1903 info2.untiltime = 0;
1905 /* These three fields must not be used by AddPrinter()
1906 as defined in the MS Platform SDK documentation..
1907 --jerry
1908 info2.status = 0;
1909 info2.cjobs = 0;
1910 info2.averageppm = 0;
1913 info_ctr.level = 2;
1914 info_ctr.info.info2 = &info2;
1916 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1917 &info_ctr);
1918 if (W_ERROR_IS_OK(result))
1919 printf ("Printer %s successfully installed.\n", argv[1]);
1921 return result;
1924 /****************************************************************************
1925 ****************************************************************************/
1927 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1928 TALLOC_CTX *mem_ctx,
1929 int argc, const char **argv)
1931 struct policy_handle pol;
1932 WERROR result;
1933 NTSTATUS status;
1934 uint32_t level = 2;
1935 const char *printername;
1936 union spoolss_PrinterInfo info;
1937 struct spoolss_SetPrinterInfoCtr info_ctr;
1938 struct spoolss_SetPrinterInfo2 info2;
1939 struct spoolss_DevmodeContainer devmode_ctr;
1940 struct sec_desc_buf secdesc_ctr;
1941 struct dcerpc_binding_handle *b = cli->binding_handle;
1943 ZERO_STRUCT(devmode_ctr);
1944 ZERO_STRUCT(secdesc_ctr);
1946 /* parse the command arguments */
1947 if (argc != 3)
1949 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1950 return WERR_OK;
1953 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1955 /* Get a printer handle */
1957 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1958 printername,
1959 PRINTER_ALL_ACCESS,
1960 &pol);
1961 if (!W_ERROR_IS_OK(result))
1962 goto done;
1964 /* Get printer info */
1966 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1967 &pol,
1968 level,
1970 &info);
1971 if (!W_ERROR_IS_OK(result)) {
1972 printf ("Unable to retrieve printer information!\n");
1973 goto done;
1976 /* Set the printer driver */
1978 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1979 info2.drivername = argv[2];
1981 info_ctr.level = 2;
1982 info_ctr.info.info2 = &info2;
1984 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1985 &pol,
1986 &info_ctr,
1987 &devmode_ctr,
1988 &secdesc_ctr,
1989 0, /* command */
1990 &result);
1991 if (!NT_STATUS_IS_OK(status)) {
1992 result = ntstatus_to_werror(status);
1993 goto done;
1995 if (!W_ERROR_IS_OK(result)) {
1996 printf("SetPrinter call failed!\n");
1997 goto done;
2000 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
2002 done:
2003 /* Cleanup */
2005 if (is_valid_policy_hnd(&pol)) {
2006 WERROR _result;
2007 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2010 return result;
2014 /****************************************************************************
2015 ****************************************************************************/
2017 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
2018 TALLOC_CTX *mem_ctx,
2019 int argc, const char **argv)
2021 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
2022 NTSTATUS status;
2023 struct dcerpc_binding_handle *b = cli->binding_handle;
2025 int i;
2026 int vers = -1;
2028 const char *arch = NULL;
2029 uint32_t delete_flags = 0;
2031 /* parse the command arguments */
2032 if (argc < 2 || argc > 5) {
2033 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
2034 return WERR_OK;
2037 if (argc >= 3)
2038 arch = argv[2];
2039 if (argc >= 4) {
2040 vers = atoi(argv[3]);
2041 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
2043 if (argc == 5)
2044 delete_flags = atoi(argv[4]);
2046 /* delete the driver for all architectures */
2047 for (i=0; archi_table[i].long_archi; i++) {
2049 if (arch && !strequal(archi_table[i].long_archi, arch))
2050 continue;
2052 if (vers >= 0 && archi_table[i].version != vers)
2053 continue;
2055 /* make the call to remove the driver */
2056 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
2057 cli->srv_name_slash,
2058 archi_table[i].long_archi,
2059 argv[1],
2060 delete_flags,
2061 archi_table[i].version,
2062 &result);
2063 if (!NT_STATUS_IS_OK(status)) {
2064 return ntstatus_to_werror(status);
2066 if ( !W_ERROR_IS_OK(result) )
2068 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2069 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2070 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
2073 else
2075 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
2076 archi_table[i].long_archi, archi_table[i].version);
2077 ret = WERR_OK;
2081 return ret;
2085 /****************************************************************************
2086 ****************************************************************************/
2088 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2089 TALLOC_CTX *mem_ctx,
2090 int argc, const char **argv)
2092 WERROR result = WERR_OK;
2093 NTSTATUS status;
2094 int i;
2095 struct dcerpc_binding_handle *b = cli->binding_handle;
2097 /* parse the command arguments */
2098 if (argc != 2) {
2099 printf ("Usage: %s <driver>\n", argv[0]);
2100 return WERR_OK;
2103 /* delete the driver for all architectures */
2104 for (i=0; archi_table[i].long_archi; i++) {
2105 result = WERR_OK;
2107 /* make the call to remove the driver */
2108 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2109 cli->srv_name_slash,
2110 archi_table[i].long_archi,
2111 argv[1],
2112 &result);
2113 if (!NT_STATUS_IS_OK(status)) {
2114 result = ntstatus_to_werror(status);
2115 continue;
2117 if ( !W_ERROR_IS_OK(result) ) {
2118 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2119 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2120 argv[1], archi_table[i].long_archi,
2121 win_errstr(result));
2123 } else {
2124 printf ("Driver %s removed for arch [%s].\n", argv[1],
2125 archi_table[i].long_archi);
2129 return result;
2132 /****************************************************************************
2133 ****************************************************************************/
2135 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2136 TALLOC_CTX *mem_ctx,
2137 int argc, const char **argv)
2139 WERROR result;
2140 NTSTATUS status;
2141 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2142 DATA_BLOB buffer;
2143 uint32_t offered;
2144 union spoolss_PrintProcessorDirectoryInfo info;
2145 uint32_t needed;
2146 struct dcerpc_binding_handle *b = cli->binding_handle;
2148 /* parse the command arguments */
2149 if (argc > 2) {
2150 printf ("Usage: %s [environment]\n", argv[0]);
2151 return WERR_OK;
2154 if (argc == 2) {
2155 environment = argv[1];
2158 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2159 cli->srv_name_slash,
2160 environment,
2162 NULL, /* buffer */
2163 0, /* offered */
2164 NULL, /* info */
2165 &needed,
2166 &result);
2167 if (!NT_STATUS_IS_OK(status)) {
2168 return ntstatus_to_werror(status);
2170 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2171 offered = needed;
2172 buffer = data_blob_talloc_zero(mem_ctx, needed);
2174 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2175 cli->srv_name_slash,
2176 environment,
2178 &buffer,
2179 offered,
2180 &info,
2181 &needed,
2182 &result);
2183 if (!NT_STATUS_IS_OK(status)) {
2184 return ntstatus_to_werror(status);
2188 if (W_ERROR_IS_OK(result)) {
2189 printf("%s\n", info.info1.directory_name);
2192 return result;
2195 /****************************************************************************
2196 ****************************************************************************/
2198 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2199 int argc, const char **argv)
2201 struct policy_handle handle;
2202 WERROR werror;
2203 NTSTATUS status;
2204 const char *printername;
2205 struct spoolss_AddFormInfoCtr info_ctr;
2206 struct spoolss_AddFormInfo1 info1;
2207 struct spoolss_AddFormInfo2 info2;
2208 uint32_t level = 1;
2209 struct dcerpc_binding_handle *b = cli->binding_handle;
2211 /* Parse the command arguments */
2213 if (argc < 3 || argc > 5) {
2214 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2215 return WERR_OK;
2218 /* Get a printer handle */
2220 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2222 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2223 printername,
2224 PRINTER_ALL_ACCESS,
2225 &handle);
2226 if (!W_ERROR_IS_OK(werror))
2227 goto done;
2229 /* Dummy up some values for the form data */
2231 if (argc == 4) {
2232 level = atoi(argv[3]);
2235 switch (level) {
2236 case 1:
2237 info1.flags = SPOOLSS_FORM_USER;
2238 info1.form_name = argv[2];
2239 info1.size.width = 100;
2240 info1.size.height = 100;
2241 info1.area.left = 0;
2242 info1.area.top = 10;
2243 info1.area.right = 20;
2244 info1.area.bottom = 30;
2246 info_ctr.level = 1;
2247 info_ctr.info.info1 = &info1;
2249 break;
2250 case 2:
2251 info2.flags = SPOOLSS_FORM_USER;
2252 info2.form_name = argv[2];
2253 info2.size.width = 100;
2254 info2.size.height = 100;
2255 info2.area.left = 0;
2256 info2.area.top = 10;
2257 info2.area.right = 20;
2258 info2.area.bottom = 30;
2259 info2.keyword = argv[2];
2260 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2261 info2.mui_dll = NULL;
2262 info2.ressource_id = 0;
2263 info2.display_name = argv[2];
2264 info2.lang_id = 0;
2266 info_ctr.level = 2;
2267 info_ctr.info.info2 = &info2;
2269 break;
2270 default:
2271 werror = WERR_INVALID_PARAMETER;
2272 goto done;
2275 /* Add the form */
2277 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2278 &handle,
2279 &info_ctr,
2280 &werror);
2281 if (!NT_STATUS_IS_OK(status)) {
2282 werror = ntstatus_to_werror(status);
2283 goto done;
2285 done:
2286 if (is_valid_policy_hnd(&handle)) {
2287 WERROR _result;
2288 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2291 return werror;
2294 /****************************************************************************
2295 ****************************************************************************/
2297 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2298 int argc, const char **argv)
2300 struct policy_handle handle;
2301 WERROR werror;
2302 NTSTATUS status;
2303 const char *printername;
2304 struct spoolss_AddFormInfoCtr info_ctr;
2305 struct spoolss_AddFormInfo1 info1;
2306 struct dcerpc_binding_handle *b = cli->binding_handle;
2308 /* Parse the command arguments */
2310 if (argc != 3) {
2311 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2312 return WERR_OK;
2315 /* Get a printer handle */
2317 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2319 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2320 printername,
2321 SEC_FLAG_MAXIMUM_ALLOWED,
2322 &handle);
2323 if (!W_ERROR_IS_OK(werror))
2324 goto done;
2326 /* Dummy up some values for the form data */
2328 info1.flags = SPOOLSS_FORM_PRINTER;
2329 info1.size.width = 100;
2330 info1.size.height = 100;
2331 info1.area.left = 0;
2332 info1.area.top = 1000;
2333 info1.area.right = 2000;
2334 info1.area.bottom = 3000;
2335 info1.form_name = argv[2];
2337 info_ctr.info.info1 = &info1;
2338 info_ctr.level = 1;
2340 /* Set the form */
2342 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2343 &handle,
2344 argv[2],
2345 &info_ctr,
2346 &werror);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 werror = ntstatus_to_werror(status);
2349 goto done;
2351 done:
2352 if (is_valid_policy_hnd(&handle)) {
2353 WERROR _result;
2354 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2357 return werror;
2360 /****************************************************************************
2361 ****************************************************************************/
2363 static const char *get_form_flag(int form_flag)
2365 switch (form_flag) {
2366 case SPOOLSS_FORM_USER:
2367 return "FORM_USER";
2368 case SPOOLSS_FORM_BUILTIN:
2369 return "FORM_BUILTIN";
2370 case SPOOLSS_FORM_PRINTER:
2371 return "FORM_PRINTER";
2372 default:
2373 return "unknown";
2377 /****************************************************************************
2378 ****************************************************************************/
2380 static void display_form_info1(struct spoolss_FormInfo1 *r)
2382 printf("%s\n" \
2383 "\tflag: %s (%d)\n" \
2384 "\twidth: %d, length: %d\n" \
2385 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2386 r->form_name, get_form_flag(r->flags), r->flags,
2387 r->size.width, r->size.height,
2388 r->area.left, r->area.right,
2389 r->area.top, r->area.bottom);
2392 /****************************************************************************
2393 ****************************************************************************/
2395 static void display_form_info2(struct spoolss_FormInfo2 *r)
2397 printf("%s\n" \
2398 "\tflag: %s (%d)\n" \
2399 "\twidth: %d, length: %d\n" \
2400 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2401 r->form_name, get_form_flag(r->flags), r->flags,
2402 r->size.width, r->size.height,
2403 r->area.left, r->area.right,
2404 r->area.top, r->area.bottom);
2405 printf("\tkeyword: %s\n", r->keyword);
2406 printf("\tstring_type: 0x%08x\n", r->string_type);
2407 printf("\tmui_dll: %s\n", r->mui_dll);
2408 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2409 printf("\tdisplay_name: %s\n", r->display_name);
2410 printf("\tlang_id: %d\n", r->lang_id);
2411 printf("\n");
2414 /****************************************************************************
2415 ****************************************************************************/
2417 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2418 int argc, const char **argv)
2420 struct policy_handle handle;
2421 WERROR werror;
2422 NTSTATUS status;
2423 const char *printername;
2424 DATA_BLOB buffer;
2425 uint32_t offered = 0;
2426 union spoolss_FormInfo info;
2427 uint32_t needed;
2428 uint32_t level = 1;
2429 struct dcerpc_binding_handle *b = cli->binding_handle;
2431 /* Parse the command arguments */
2433 if (argc < 3 || argc > 5) {
2434 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2435 return WERR_OK;
2438 /* Get a printer handle */
2440 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2442 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2443 printername,
2444 SEC_FLAG_MAXIMUM_ALLOWED,
2445 &handle);
2446 if (!W_ERROR_IS_OK(werror))
2447 goto done;
2449 if (argc == 4) {
2450 level = atoi(argv[3]);
2453 /* Get the form */
2455 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2456 &handle,
2457 argv[2],
2458 level,
2459 NULL,
2460 offered,
2461 &info,
2462 &needed,
2463 &werror);
2464 if (!NT_STATUS_IS_OK(status)) {
2465 werror = ntstatus_to_werror(status);
2466 goto done;
2468 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2469 buffer = data_blob_talloc_zero(mem_ctx, needed);
2470 offered = needed;
2471 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2472 &handle,
2473 argv[2],
2474 level,
2475 &buffer,
2476 offered,
2477 &info,
2478 &needed,
2479 &werror);
2480 if (!NT_STATUS_IS_OK(status)) {
2481 werror = ntstatus_to_werror(status);
2482 goto done;
2486 if (!W_ERROR_IS_OK(werror)) {
2487 goto done;
2490 switch (level) {
2491 case 1:
2492 display_form_info1(&info.info1);
2493 break;
2494 case 2:
2495 display_form_info2(&info.info2);
2496 break;
2499 done:
2500 if (is_valid_policy_hnd(&handle)) {
2501 WERROR _result;
2502 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2505 return werror;
2508 /****************************************************************************
2509 ****************************************************************************/
2511 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2512 TALLOC_CTX *mem_ctx, int argc,
2513 const char **argv)
2515 struct policy_handle handle;
2516 WERROR werror;
2517 NTSTATUS status;
2518 const char *printername;
2519 struct dcerpc_binding_handle *b = cli->binding_handle;
2521 /* Parse the command arguments */
2523 if (argc != 3) {
2524 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2525 return WERR_OK;
2528 /* Get a printer handle */
2530 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2532 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2533 printername,
2534 SEC_FLAG_MAXIMUM_ALLOWED,
2535 &handle);
2536 if (!W_ERROR_IS_OK(werror))
2537 goto done;
2539 /* Delete the form */
2541 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2542 &handle,
2543 argv[2],
2544 &werror);
2545 if (!NT_STATUS_IS_OK(status)) {
2546 werror = ntstatus_to_werror(status);
2547 goto done;
2550 done:
2551 if (is_valid_policy_hnd(&handle)) {
2552 WERROR _result;
2553 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2556 return werror;
2559 /****************************************************************************
2560 ****************************************************************************/
2562 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2563 TALLOC_CTX *mem_ctx, int argc,
2564 const char **argv)
2566 struct policy_handle handle;
2567 WERROR werror;
2568 const char *printername;
2569 uint32_t num_forms, level = 1, i;
2570 union spoolss_FormInfo *forms;
2571 struct dcerpc_binding_handle *b = cli->binding_handle;
2573 /* Parse the command arguments */
2575 if (argc < 2 || argc > 4) {
2576 printf ("Usage: %s <printer> [level]\n", argv[0]);
2577 return WERR_OK;
2580 /* Get a printer handle */
2582 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2584 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2585 printername,
2586 SEC_FLAG_MAXIMUM_ALLOWED,
2587 &handle);
2588 if (!W_ERROR_IS_OK(werror))
2589 goto done;
2591 if (argc == 3) {
2592 level = atoi(argv[2]);
2595 /* Enumerate forms */
2597 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2598 &handle,
2599 level,
2601 &num_forms,
2602 &forms);
2604 if (!W_ERROR_IS_OK(werror))
2605 goto done;
2607 /* Display output */
2609 for (i = 0; i < num_forms; i++) {
2610 switch (level) {
2611 case 1:
2612 display_form_info1(&forms[i].info1);
2613 break;
2614 case 2:
2615 display_form_info2(&forms[i].info2);
2616 break;
2620 done:
2621 if (is_valid_policy_hnd(&handle)) {
2622 WERROR _result;
2623 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2626 return werror;
2629 /****************************************************************************
2630 ****************************************************************************/
2632 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2633 TALLOC_CTX *mem_ctx,
2634 int argc, const char **argv)
2636 WERROR result;
2637 NTSTATUS status;
2638 const char *printername;
2639 struct policy_handle pol = { 0, };
2640 union spoolss_PrinterInfo info;
2641 enum winreg_Type type;
2642 union spoolss_PrinterData data;
2643 DATA_BLOB blob;
2644 struct dcerpc_binding_handle *b = cli->binding_handle;
2645 int error = 0;
2647 /* parse the command arguments */
2648 if (argc < 5) {
2649 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2650 " <value> <data>\n",
2651 argv[0]);
2652 return WERR_OK;
2655 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2657 type = REG_NONE;
2659 if (strequal(argv[2], "string")) {
2660 type = REG_SZ;
2663 if (strequal(argv[2], "binary")) {
2664 type = REG_BINARY;
2667 if (strequal(argv[2], "dword")) {
2668 type = REG_DWORD;
2671 if (strequal(argv[2], "multistring")) {
2672 type = REG_MULTI_SZ;
2675 if (type == REG_NONE) {
2676 printf("Unknown data type: %s\n", argv[2]);
2677 result = WERR_INVALID_PARAMETER;
2678 goto done;
2681 /* get a printer handle */
2683 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2684 printername,
2685 SEC_FLAG_MAXIMUM_ALLOWED,
2686 &pol);
2687 if (!W_ERROR_IS_OK(result)) {
2688 goto done;
2691 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2692 &pol,
2695 &info);
2696 if (!W_ERROR_IS_OK(result)) {
2697 goto done;
2700 printf("%s\n", current_timestring(mem_ctx, true));
2701 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2703 /* Set the printer data */
2705 switch (type) {
2706 case REG_SZ:
2707 data.string = talloc_strdup(mem_ctx, argv[4]);
2708 W_ERROR_HAVE_NO_MEMORY(data.string);
2709 break;
2710 case REG_DWORD:
2711 data.value = smb_strtoul(argv[4],
2712 NULL,
2714 &error,
2715 SMB_STR_STANDARD);
2716 if (error != 0) {
2717 result = WERR_INVALID_PARAMETER;
2718 goto done;
2721 break;
2722 case REG_BINARY:
2723 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2724 break;
2725 case REG_MULTI_SZ: {
2726 int i;
2727 size_t num_strings;
2728 const char **strings = NULL;
2730 num_strings = 0;
2732 for (i=4; i<argc; i++) {
2733 if (strcmp(argv[i], "NULL") == 0) {
2734 argv[i] = "";
2736 if (!add_string_to_array(mem_ctx, argv[i],
2737 &strings,
2738 &num_strings)) {
2739 result = WERR_NOT_ENOUGH_MEMORY;
2740 goto done;
2743 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2744 if (!data.string_array) {
2745 result = WERR_NOT_ENOUGH_MEMORY;
2746 goto done;
2748 for (i=0; i < num_strings; i++) {
2749 data.string_array[i] = strings[i];
2751 break;
2753 default:
2754 printf("Unknown data type: %s\n", argv[2]);
2755 result = WERR_INVALID_PARAMETER;
2756 goto done;
2759 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2760 if (!W_ERROR_IS_OK(result)) {
2761 goto done;
2764 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2765 &pol,
2766 argv[3], /* value_name */
2767 type,
2768 blob.data,
2769 blob.length,
2770 &result);
2771 if (!NT_STATUS_IS_OK(status)) {
2772 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2773 result = ntstatus_to_werror(status);
2774 goto done;
2776 if (!W_ERROR_IS_OK(result)) {
2777 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2778 goto done;
2780 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2782 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2783 &pol,
2786 &info);
2787 if (!W_ERROR_IS_OK(result)) {
2788 goto done;
2791 printf("%s\n", current_timestring(mem_ctx, true));
2792 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2794 done:
2795 /* cleanup */
2796 if (is_valid_policy_hnd(&pol)) {
2797 WERROR _result;
2798 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2801 return result;
2804 /****************************************************************************
2805 ****************************************************************************/
2807 static void display_job_info1(struct spoolss_JobInfo1 *r)
2809 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2810 r->user_name, r->document_name, r->text_status, r->pages_printed,
2811 r->total_pages);
2814 /****************************************************************************
2815 ****************************************************************************/
2817 static void display_job_info2(struct spoolss_JobInfo2 *r)
2819 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2820 r->position, r->job_id,
2821 r->user_name, r->document_name, r->text_status, r->pages_printed,
2822 r->total_pages, r->size);
2825 /****************************************************************************
2826 ****************************************************************************/
2828 static void display_job_info3(struct spoolss_JobInfo3 *r)
2830 printf("jobid[%d], next_jobid[%d]\n",
2831 r->job_id, r->next_job_id);
2834 /****************************************************************************
2835 ****************************************************************************/
2837 static void display_job_info4(struct spoolss_JobInfo4 *r)
2839 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2840 r->position, r->job_id,
2841 r->user_name, r->document_name, r->text_status, r->pages_printed,
2842 r->total_pages, r->size, r->size_high);
2845 /****************************************************************************
2846 ****************************************************************************/
2848 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2849 TALLOC_CTX *mem_ctx, int argc,
2850 const char **argv)
2852 WERROR result;
2853 uint32_t level = 1, count, i;
2854 const char *printername;
2855 struct policy_handle hnd;
2856 union spoolss_JobInfo *info;
2857 struct dcerpc_binding_handle *b = cli->binding_handle;
2859 if (argc < 2 || argc > 3) {
2860 printf("Usage: %s printername [level]\n", argv[0]);
2861 return WERR_OK;
2864 if (argc == 3) {
2865 level = atoi(argv[2]);
2868 /* Open printer handle */
2870 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2872 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2873 printername,
2874 SEC_FLAG_MAXIMUM_ALLOWED,
2875 &hnd);
2876 if (!W_ERROR_IS_OK(result))
2877 goto done;
2879 /* Enumerate ports */
2881 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2882 &hnd,
2883 0, /* firstjob */
2884 1000, /* numjobs */
2885 level,
2887 &count,
2888 &info);
2889 if (!W_ERROR_IS_OK(result)) {
2890 goto done;
2893 for (i = 0; i < count; i++) {
2894 switch (level) {
2895 case 1:
2896 display_job_info1(&info[i].info1);
2897 break;
2898 case 2:
2899 display_job_info2(&info[i].info2);
2900 break;
2901 default:
2902 d_printf("unknown info level %d\n", level);
2903 break;
2907 done:
2908 if (is_valid_policy_hnd(&hnd)) {
2909 WERROR _result;
2910 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2913 return result;
2916 /****************************************************************************
2917 ****************************************************************************/
2919 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2920 TALLOC_CTX *mem_ctx, int argc,
2921 const char **argv)
2923 WERROR result;
2924 const char *printername;
2925 struct policy_handle hnd;
2926 uint32_t job_id;
2927 uint32_t level = 1;
2928 union spoolss_JobInfo info;
2929 struct dcerpc_binding_handle *b = cli->binding_handle;
2931 if (argc < 3 || argc > 4) {
2932 printf("Usage: %s printername job_id [level]\n", argv[0]);
2933 return WERR_OK;
2936 job_id = atoi(argv[2]);
2938 if (argc == 4) {
2939 level = atoi(argv[3]);
2942 /* Open printer handle */
2944 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2946 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2947 printername,
2948 SEC_FLAG_MAXIMUM_ALLOWED,
2949 &hnd);
2950 if (!W_ERROR_IS_OK(result)) {
2951 goto done;
2954 /* Enumerate ports */
2956 result = rpccli_spoolss_getjob(cli, mem_ctx,
2957 &hnd,
2958 job_id,
2959 level,
2961 &info);
2963 if (!W_ERROR_IS_OK(result)) {
2964 goto done;
2967 switch (level) {
2968 case 1:
2969 display_job_info1(&info.info1);
2970 break;
2971 case 2:
2972 display_job_info2(&info.info2);
2973 break;
2974 case 3:
2975 display_job_info3(&info.info3);
2976 break;
2977 case 4:
2978 display_job_info4(&info.info4);
2979 break;
2980 default:
2981 d_printf("unknown info level %d\n", level);
2982 break;
2985 done:
2986 if (is_valid_policy_hnd(&hnd)) {
2987 WERROR _result;
2988 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2991 return result;
2994 /****************************************************************************
2995 ****************************************************************************/
2997 static struct {
2998 const char *name;
2999 enum spoolss_JobControl val;
3000 } cmdvals[] = {
3001 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
3002 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
3003 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
3004 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
3005 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
3006 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
3007 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
3008 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
3009 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
3012 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
3014 int i;
3016 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
3017 if (strequal(cmdvals[i].name, cmd)) {
3018 return cmdvals[i].val;
3021 return (enum spoolss_JobControl)atoi(cmd);
3024 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
3025 TALLOC_CTX *mem_ctx, int argc,
3026 const char **argv)
3028 WERROR result;
3029 NTSTATUS status;
3030 const char *printername;
3031 struct policy_handle hnd;
3032 uint32_t job_id;
3033 enum spoolss_JobControl command;
3034 struct dcerpc_binding_handle *b = cli->binding_handle;
3036 if (argc != 4) {
3037 printf("Usage: %s printername job_id command\n", argv[0]);
3038 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3039 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3040 return WERR_OK;
3043 job_id = atoi(argv[2]);
3044 command = parse_setjob_command(argv[3]);
3046 /* Open printer handle */
3048 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3050 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3051 printername,
3052 SEC_FLAG_MAXIMUM_ALLOWED,
3053 &hnd);
3054 if (!W_ERROR_IS_OK(result)) {
3055 goto done;
3058 /* Set Job */
3060 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3061 &hnd,
3062 job_id,
3063 NULL,
3064 command,
3065 &result);
3066 if (!NT_STATUS_IS_OK(status)) {
3067 result = ntstatus_to_werror(status);
3068 goto done;
3070 if (!W_ERROR_IS_OK(result)) {
3071 goto done;
3074 done:
3075 if (is_valid_policy_hnd(&hnd)) {
3076 WERROR _result;
3077 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3080 return result;
3083 /****************************************************************************
3084 ****************************************************************************/
3086 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
3087 TALLOC_CTX *mem_ctx, int argc,
3088 const char **argv)
3090 WERROR result;
3091 NTSTATUS status;
3092 const char *printername;
3093 struct policy_handle hnd;
3094 uint32_t value_needed;
3095 enum winreg_Type type;
3096 uint32_t data_needed;
3097 struct dcerpc_binding_handle *b = cli->binding_handle;
3098 struct spoolss_EnumPrinterData r;
3100 if (argc != 2) {
3101 printf("Usage: %s printername\n", argv[0]);
3102 return WERR_OK;
3105 /* Open printer handle */
3107 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3109 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3110 printername,
3111 SEC_FLAG_MAXIMUM_ALLOWED,
3112 &hnd);
3113 if (!W_ERROR_IS_OK(result)) {
3114 goto done;
3117 /* Enumerate data */
3119 r.in.handle = &hnd;
3120 r.in.enum_index = 0;
3121 r.in.value_offered = 0;
3122 r.in.data_offered = 0;
3123 r.out.value_name = NULL;
3124 r.out.value_needed = &value_needed;
3125 r.out.type = &type;
3126 r.out.data = NULL;
3127 r.out.data_needed = &data_needed;
3129 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3130 if (!NT_STATUS_IS_OK(status)) {
3131 result = ntstatus_to_werror(status);
3132 goto done;
3135 if (!W_ERROR_IS_OK(r.out.result)) {
3136 result = r.out.result;
3137 goto done;
3140 r.in.data_offered = *r.out.data_needed;
3141 r.in.value_offered = *r.out.value_needed;
3142 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3143 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3145 do {
3147 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3148 if (!NT_STATUS_IS_OK(status)) {
3149 result = ntstatus_to_werror(status);
3150 goto done;
3153 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3154 result = WERR_OK;
3155 break;
3158 r.in.enum_index++;
3160 display_reg_value(r.out.value_name, *r.out.type,
3161 data_blob_const(r.out.data, r.in.data_offered));
3163 } while (W_ERROR_IS_OK(r.out.result));
3165 done:
3166 if (is_valid_policy_hnd(&hnd)) {
3167 WERROR _result;
3168 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3171 return result;
3174 /****************************************************************************
3175 ****************************************************************************/
3177 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3178 TALLOC_CTX *mem_ctx, int argc,
3179 const char **argv)
3181 WERROR result;
3182 uint32_t i;
3183 const char *printername;
3184 struct policy_handle hnd;
3185 uint32_t count;
3186 struct spoolss_PrinterEnumValues *info;
3187 struct dcerpc_binding_handle *b = cli->binding_handle;
3189 if (argc != 3) {
3190 printf("Usage: %s printername <keyname>\n", argv[0]);
3191 return WERR_OK;
3194 /* Open printer handle */
3196 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3198 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3199 printername,
3200 SEC_FLAG_MAXIMUM_ALLOWED,
3201 &hnd);
3202 if (!W_ERROR_IS_OK(result)) {
3203 goto done;
3206 /* Enumerate subkeys */
3208 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3209 &hnd,
3210 argv[2],
3212 &count,
3213 &info);
3214 if (!W_ERROR_IS_OK(result)) {
3215 goto done;
3218 for (i=0; i < count; i++) {
3219 display_printer_data(info[i].value_name,
3220 info[i].type,
3221 info[i].data->data,
3222 info[i].data->length);
3225 done:
3226 if (is_valid_policy_hnd(&hnd)) {
3227 WERROR _result;
3228 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3231 return result;
3234 /****************************************************************************
3235 ****************************************************************************/
3237 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3238 TALLOC_CTX *mem_ctx, int argc,
3239 const char **argv)
3241 WERROR result;
3242 const char *printername;
3243 const char *keyname = NULL;
3244 struct policy_handle hnd;
3245 const char **key_buffer = NULL;
3246 int i;
3247 uint32_t offered = 0;
3248 struct dcerpc_binding_handle *b = cli->binding_handle;
3250 if (argc < 2 || argc > 4) {
3251 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3252 return WERR_OK;
3255 if (argc >= 3) {
3256 keyname = argv[2];
3257 } else {
3258 keyname = "";
3261 if (argc == 4) {
3262 offered = atoi(argv[3]);
3265 /* Open printer handle */
3267 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3269 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3270 printername,
3271 SEC_FLAG_MAXIMUM_ALLOWED,
3272 &hnd);
3273 if (!W_ERROR_IS_OK(result)) {
3274 goto done;
3277 /* Enumerate subkeys */
3279 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3280 &hnd,
3281 keyname,
3282 &key_buffer,
3283 offered);
3285 if (!W_ERROR_IS_OK(result)) {
3286 goto done;
3289 for (i=0; key_buffer && key_buffer[i]; i++) {
3290 printf("%s\n", key_buffer[i]);
3293 done:
3295 if (is_valid_policy_hnd(&hnd)) {
3296 WERROR _result;
3297 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3300 return result;
3303 /****************************************************************************
3304 ****************************************************************************/
3306 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3307 TALLOC_CTX *mem_ctx, int argc,
3308 const char **argv)
3310 const char *printername;
3311 const char *clientname;
3312 struct policy_handle hnd = { 0, };
3313 WERROR result;
3314 NTSTATUS status;
3315 struct spoolss_NotifyOption option;
3316 struct dcerpc_binding_handle *b = cli->binding_handle;
3318 if (argc != 2) {
3319 printf("Usage: %s printername\n", argv[0]);
3320 result = WERR_OK;
3321 goto done;
3324 /* Open printer */
3326 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3328 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3329 printername,
3330 SEC_FLAG_MAXIMUM_ALLOWED,
3331 &hnd);
3332 if (!W_ERROR_IS_OK(result)) {
3333 printf("Error opening %s\n", argv[1]);
3334 goto done;
3337 /* Create spool options */
3339 option.version = 2;
3340 option.count = 2;
3342 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3343 if (option.types == NULL) {
3344 result = WERR_NOT_ENOUGH_MEMORY;
3345 goto done;
3348 option.types[0].type = PRINTER_NOTIFY_TYPE;
3349 option.types[0].count = 1;
3350 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3351 if (option.types[0].fields == NULL) {
3352 result = WERR_NOT_ENOUGH_MEMORY;
3353 goto done;
3355 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3357 option.types[1].type = JOB_NOTIFY_TYPE;
3358 option.types[1].count = 1;
3359 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3360 if (option.types[1].fields == NULL) {
3361 result = WERR_NOT_ENOUGH_MEMORY;
3362 goto done;
3364 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3366 clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3367 if (!clientname) {
3368 result = WERR_NOT_ENOUGH_MEMORY;
3369 goto done;
3372 /* Send rffpcnex */
3374 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3375 &hnd,
3378 clientname,
3379 123,
3380 &option,
3381 &result);
3382 if (!NT_STATUS_IS_OK(status)) {
3383 result = ntstatus_to_werror(status);
3384 goto done;
3386 if (!W_ERROR_IS_OK(result)) {
3387 printf("Error rffpcnex %s\n", argv[1]);
3388 goto done;
3391 done:
3392 if (is_valid_policy_hnd(&hnd)) {
3393 WERROR _result;
3394 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3397 return result;
3400 /****************************************************************************
3401 ****************************************************************************/
3403 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3404 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3406 union spoolss_PrinterInfo info1, info2;
3407 WERROR werror;
3408 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3410 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3411 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3412 hnd1,
3415 &info1);
3416 if ( !W_ERROR_IS_OK(werror) ) {
3417 printf("failed (%s)\n", win_errstr(werror));
3418 talloc_destroy(mem_ctx);
3419 return false;
3421 printf("ok\n");
3423 printf("Retrieving printer properties for %s...", cli2->desthost);
3424 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3425 hnd2,
3428 &info2);
3429 if ( !W_ERROR_IS_OK(werror) ) {
3430 printf("failed (%s)\n", win_errstr(werror));
3431 talloc_destroy(mem_ctx);
3432 return false;
3434 printf("ok\n");
3436 talloc_destroy(mem_ctx);
3438 return true;
3441 /****************************************************************************
3442 ****************************************************************************/
3444 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3445 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3447 union spoolss_PrinterInfo info1, info2;
3448 WERROR werror;
3449 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3450 struct security_descriptor *sd1, *sd2;
3451 bool result = true;
3454 printf("Retrieving printer security for %s...", cli1->desthost);
3455 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3456 hnd1,
3459 &info1);
3460 if ( !W_ERROR_IS_OK(werror) ) {
3461 printf("failed (%s)\n", win_errstr(werror));
3462 result = false;
3463 goto done;
3465 printf("ok\n");
3467 printf("Retrieving printer security for %s...", cli2->desthost);
3468 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3469 hnd2,
3472 &info2);
3473 if ( !W_ERROR_IS_OK(werror) ) {
3474 printf("failed (%s)\n", win_errstr(werror));
3475 result = false;
3476 goto done;
3478 printf("ok\n");
3481 printf("++ ");
3483 sd1 = info1.info3.secdesc;
3484 sd2 = info2.info3.secdesc;
3486 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3487 printf("NULL secdesc!\n");
3488 result = false;
3489 goto done;
3492 if (!security_descriptor_equal( sd1, sd2 ) ) {
3493 printf("Security Descriptors *not* equal!\n");
3494 result = false;
3495 goto done;
3498 printf("Security descriptors match\n");
3500 done:
3501 talloc_destroy(mem_ctx);
3502 return result;
3506 /****************************************************************************
3507 ****************************************************************************/
3509 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3510 TALLOC_CTX *mem_ctx, int argc,
3511 const char **argv)
3513 const char *printername;
3514 char *printername_path = NULL;
3515 struct cli_state *cli_server2 = NULL;
3516 struct rpc_pipe_client *cli2 = NULL;
3517 struct policy_handle hPrinter1, hPrinter2;
3518 NTSTATUS nt_status;
3519 WERROR werror;
3521 if ( argc != 3 ) {
3522 printf("Usage: %s <printer> <server>\n", argv[0]);
3523 return WERR_OK;
3526 printername = argv[1];
3528 /* first get the connection to the remote server */
3530 nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
3531 NULL, 0,
3532 "IPC$", "IPC",
3533 get_cmdline_auth_info_username(
3534 popt_get_cmdline_auth_info()),
3535 lp_workgroup(),
3536 get_cmdline_auth_info_password(
3537 popt_get_cmdline_auth_info()),
3538 get_cmdline_auth_info_use_kerberos(
3539 popt_get_cmdline_auth_info()) ?
3540 CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3541 get_cmdline_auth_info_signing_state(
3542 popt_get_cmdline_auth_info()));
3544 if ( !NT_STATUS_IS_OK(nt_status) )
3545 return WERR_GEN_FAILURE;
3547 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3548 &cli2);
3549 if (!NT_STATUS_IS_OK(nt_status)) {
3550 printf("failed to open spoolss pipe on server %s (%s)\n",
3551 argv[2], nt_errstr(nt_status));
3552 return WERR_GEN_FAILURE;
3555 /* now open up both printers */
3557 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3559 printf("Opening %s...", printername_path);
3561 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3562 printername_path,
3563 PRINTER_ALL_ACCESS,
3564 &hPrinter1);
3565 if ( !W_ERROR_IS_OK(werror) ) {
3566 printf("failed (%s)\n", win_errstr(werror));
3567 goto done;
3569 printf("ok\n");
3571 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3573 printf("Opening %s...", printername_path);
3574 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3575 printername_path,
3576 PRINTER_ALL_ACCESS,
3577 &hPrinter2);
3578 if ( !W_ERROR_IS_OK(werror) ) {
3579 printf("failed (%s)\n", win_errstr(werror));
3580 goto done;
3582 printf("ok\n");
3584 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3585 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3586 #if 0
3587 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3588 #endif
3591 done:
3592 /* cleanup */
3594 printf("Closing printers...");
3596 WERROR _result;
3597 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3598 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3600 printf("ok\n");
3602 /* close the second remote connection */
3604 cli_shutdown( cli_server2 );
3605 return WERR_OK;
3608 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3610 printf("print_processor_name: %s\n", r->print_processor_name);
3613 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3614 TALLOC_CTX *mem_ctx, int argc,
3615 const char **argv)
3617 WERROR werror;
3618 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3619 uint32_t num_procs, level = 1, i;
3620 union spoolss_PrintProcessorInfo *procs;
3622 /* Parse the command arguments */
3624 if (argc < 1 || argc > 4) {
3625 printf ("Usage: %s [environment] [level]\n", argv[0]);
3626 return WERR_OK;
3629 if (argc >= 2) {
3630 environment = argv[1];
3633 if (argc == 3) {
3634 level = atoi(argv[2]);
3637 /* Enumerate Print Processors */
3639 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3640 cli->srv_name_slash,
3641 environment,
3642 level,
3644 &num_procs,
3645 &procs);
3646 if (!W_ERROR_IS_OK(werror))
3647 goto done;
3649 /* Display output */
3651 for (i = 0; i < num_procs; i++) {
3652 switch (level) {
3653 case 1:
3654 display_proc_info1(&procs[i].info1);
3655 break;
3659 done:
3660 return werror;
3663 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3665 printf("name_array: %s\n", r->name_array);
3668 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3669 TALLOC_CTX *mem_ctx, int argc,
3670 const char **argv)
3672 WERROR werror;
3673 const char *print_processor_name = "winprint";
3674 uint32_t num_procs, level = 1, i;
3675 union spoolss_PrintProcDataTypesInfo *procs;
3677 /* Parse the command arguments */
3679 if (argc < 1 || argc > 4) {
3680 printf ("Usage: %s [environment] [level]\n", argv[0]);
3681 return WERR_OK;
3684 if (argc >= 2) {
3685 print_processor_name = argv[1];
3688 if (argc == 3) {
3689 level = atoi(argv[2]);
3692 /* Enumerate Print Processor Data Types */
3694 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3695 cli->srv_name_slash,
3696 print_processor_name,
3697 level,
3699 &num_procs,
3700 &procs);
3701 if (!W_ERROR_IS_OK(werror))
3702 goto done;
3704 /* Display output */
3706 for (i = 0; i < num_procs; i++) {
3707 switch (level) {
3708 case 1:
3709 display_proc_data_types_info1(&procs[i].info1);
3710 break;
3714 done:
3715 return werror;
3718 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3720 printf("monitor_name: %s\n", r->monitor_name);
3723 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3725 printf("monitor_name: %s\n", r->monitor_name);
3726 printf("environment: %s\n", r->environment);
3727 printf("dll_name: %s\n", r->dll_name);
3730 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3731 TALLOC_CTX *mem_ctx, int argc,
3732 const char **argv)
3734 WERROR werror;
3735 uint32_t count, level = 1, i;
3736 union spoolss_MonitorInfo *info;
3738 /* Parse the command arguments */
3740 if (argc > 2) {
3741 printf("Usage: %s [level]\n", argv[0]);
3742 return WERR_OK;
3745 if (argc == 2) {
3746 level = atoi(argv[1]);
3749 /* Enumerate Print Monitors */
3751 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3752 cli->srv_name_slash,
3753 level,
3755 &count,
3756 &info);
3757 if (!W_ERROR_IS_OK(werror)) {
3758 goto done;
3761 /* Display output */
3763 for (i = 0; i < count; i++) {
3764 switch (level) {
3765 case 1:
3766 display_monitor1(&info[i].info1);
3767 break;
3768 case 2:
3769 display_monitor2(&info[i].info2);
3770 break;
3774 done:
3775 return werror;
3778 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3779 TALLOC_CTX *mem_ctx, int argc,
3780 const char **argv)
3782 WERROR result;
3783 NTSTATUS status;
3784 struct policy_handle handle, gdi_handle;
3785 const char *printername;
3786 struct spoolss_DevmodeContainer devmode_ctr;
3787 struct dcerpc_binding_handle *b = cli->binding_handle;
3789 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3791 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3792 printername,
3793 SEC_FLAG_MAXIMUM_ALLOWED,
3794 &handle);
3795 if (!W_ERROR_IS_OK(result)) {
3796 return result;
3799 ZERO_STRUCT(devmode_ctr);
3801 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3802 &handle,
3803 &gdi_handle,
3804 &devmode_ctr,
3805 &result);
3806 if (!NT_STATUS_IS_OK(status)) {
3807 result = ntstatus_to_werror(status);
3808 goto done;
3810 if (!W_ERROR_IS_OK(result)) {
3811 goto done;
3814 done:
3815 if (is_valid_policy_hnd(&gdi_handle)) {
3816 WERROR _result;
3817 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3819 if (is_valid_policy_hnd(&handle)) {
3820 WERROR _result;
3821 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3824 return result;
3827 static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3828 TALLOC_CTX *mem_ctx, int argc,
3829 const char **argv)
3831 WERROR result;
3832 NTSTATUS status;
3833 struct policy_handle handle, gdi_handle;
3834 const char *printername;
3835 struct spoolss_DevmodeContainer devmode_ctr;
3836 struct dcerpc_binding_handle *b = cli->binding_handle;
3837 DATA_BLOB in,out;
3838 uint32_t count = 0;
3840 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3842 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3843 printername,
3844 SEC_FLAG_MAXIMUM_ALLOWED,
3845 &handle);
3846 if (!W_ERROR_IS_OK(result)) {
3847 return result;
3850 ZERO_STRUCT(devmode_ctr);
3852 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3853 &handle,
3854 &gdi_handle,
3855 &devmode_ctr,
3856 &result);
3857 if (!NT_STATUS_IS_OK(status)) {
3858 result = ntstatus_to_werror(status);
3859 goto done;
3861 if (!W_ERROR_IS_OK(result)) {
3862 goto done;
3865 in = data_blob_string_const("");
3866 out = data_blob_talloc_zero(mem_ctx, 4);
3868 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3869 &gdi_handle,
3870 in.data,
3871 in.length,
3872 out.data,
3873 out.length,
3874 0, /* ul */
3875 &result);
3876 if (!NT_STATUS_IS_OK(status)) {
3877 result = ntstatus_to_werror(status);
3878 goto done;
3880 if (!W_ERROR_IS_OK(result)) {
3881 goto done;
3884 count = IVAL(out.data, 0);
3886 out = data_blob_talloc_zero(mem_ctx,
3887 count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3889 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3890 &gdi_handle,
3891 in.data,
3892 in.length,
3893 out.data,
3894 out.length,
3895 0, /* ul */
3896 &result);
3897 if (!NT_STATUS_IS_OK(status)) {
3898 result = ntstatus_to_werror(status);
3899 goto done;
3901 if (!W_ERROR_IS_OK(result)) {
3902 goto done;
3906 enum ndr_err_code ndr_err;
3907 struct UNIVERSAL_FONT_ID_ctr r;
3909 ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3910 (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3911 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3912 NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3916 done:
3917 if (is_valid_policy_hnd(&gdi_handle)) {
3918 WERROR _result;
3919 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3921 if (is_valid_policy_hnd(&handle)) {
3922 WERROR _result;
3923 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3926 return result;
3929 /* List of commands exported by this module */
3930 struct cmd_set spoolss_commands[] = {
3933 .name = "SPOOLSS",
3937 .name = "adddriver",
3938 .returntype = RPC_RTYPE_WERROR,
3939 .ntfn = NULL,
3940 .wfn = cmd_spoolss_addprinterdriver,
3941 .table = &ndr_table_spoolss,
3942 .rpc_pipe = NULL,
3943 .description = "Add a print driver",
3944 .usage = "",
3945 .use_netlogon_creds = false,
3948 .name = "addprinter",
3949 .returntype = RPC_RTYPE_WERROR,
3950 .ntfn = NULL,
3951 .wfn = cmd_spoolss_addprinterex,
3952 .table = &ndr_table_spoolss,
3953 .rpc_pipe = NULL,
3954 .description = "Add a printer",
3955 .usage = "",
3958 .name = "deldriver",
3959 .returntype = RPC_RTYPE_WERROR,
3960 .ntfn = NULL,
3961 .wfn = cmd_spoolss_deletedriver,
3962 .table = &ndr_table_spoolss,
3963 .rpc_pipe = NULL,
3964 .description = "Delete a printer driver",
3965 .usage = "",
3968 .name = "deldriverex",
3969 .returntype = RPC_RTYPE_WERROR,
3970 .ntfn = NULL,
3971 .wfn = cmd_spoolss_deletedriverex,
3972 .table = &ndr_table_spoolss,
3973 .rpc_pipe = NULL,
3974 .description = "Delete a printer driver with files",
3975 .usage = "",
3978 .name = "enumdata",
3979 .returntype = RPC_RTYPE_WERROR,
3980 .ntfn = NULL,
3981 .wfn = cmd_spoolss_enum_data,
3982 .table = &ndr_table_spoolss,
3983 .rpc_pipe = NULL,
3984 .description = "Enumerate printer data",
3985 .usage = "",
3988 .name = "enumdataex",
3989 .returntype = RPC_RTYPE_WERROR,
3990 .ntfn = NULL,
3991 .wfn = cmd_spoolss_enum_data_ex,
3992 .table = &ndr_table_spoolss,
3993 .rpc_pipe = NULL,
3994 .description = "Enumerate printer data for a key",
3995 .usage = "",
3998 .name = "enumkey",
3999 .returntype = RPC_RTYPE_WERROR,
4000 .ntfn = NULL,
4001 .wfn = cmd_spoolss_enum_printerkey,
4002 .table = &ndr_table_spoolss,
4003 .rpc_pipe = NULL,
4004 .description = "Enumerate printer keys",
4005 .usage = "",
4008 .name = "enumjobs",
4009 .returntype = RPC_RTYPE_WERROR,
4010 .ntfn = NULL,
4011 .wfn = cmd_spoolss_enum_jobs,
4012 .table = &ndr_table_spoolss,
4013 .rpc_pipe = NULL,
4014 .description = "Enumerate print jobs",
4015 .usage = "",
4018 .name = "getjob",
4019 .returntype = RPC_RTYPE_WERROR,
4020 .ntfn = NULL,
4021 .wfn = cmd_spoolss_get_job,
4022 .table = &ndr_table_spoolss,
4023 .rpc_pipe = NULL,
4024 .description = "Get print job",
4025 .usage = "",
4028 .name = "setjob",
4029 .returntype = RPC_RTYPE_WERROR,
4030 .ntfn = NULL,
4031 .wfn = cmd_spoolss_set_job,
4032 .table = &ndr_table_spoolss,
4033 .rpc_pipe = NULL,
4034 .description = "Set print job",
4035 .usage = "",
4038 .name = "enumports",
4039 .returntype = RPC_RTYPE_WERROR,
4040 .ntfn = NULL,
4041 .wfn = cmd_spoolss_enum_ports,
4042 .table = &ndr_table_spoolss,
4043 .rpc_pipe = NULL,
4044 .description = "Enumerate printer ports",
4045 .usage = "",
4048 .name = "enumdrivers",
4049 .returntype = RPC_RTYPE_WERROR,
4050 .ntfn = NULL,
4051 .wfn = cmd_spoolss_enum_drivers,
4052 .table = &ndr_table_spoolss,
4053 .rpc_pipe = NULL,
4054 .description = "Enumerate installed printer drivers",
4055 .usage = "",
4058 .name = "enumprinters",
4059 .returntype = RPC_RTYPE_WERROR,
4060 .ntfn = NULL,
4061 .wfn = cmd_spoolss_enum_printers,
4062 .table = &ndr_table_spoolss,
4063 .rpc_pipe = NULL,
4064 .description = "Enumerate printers",
4065 .usage = "",
4068 .name = "getdata",
4069 .returntype = RPC_RTYPE_WERROR,
4070 .ntfn = NULL,
4071 .wfn = cmd_spoolss_getprinterdata,
4072 .table = &ndr_table_spoolss,
4073 .rpc_pipe = NULL,
4074 .description = "Get print driver data",
4075 .usage = "",
4078 .name = "getdataex",
4079 .returntype = RPC_RTYPE_WERROR,
4080 .ntfn = NULL,
4081 .wfn = cmd_spoolss_getprinterdataex,
4082 .table = &ndr_table_spoolss,
4083 .rpc_pipe = NULL,
4084 .description = "Get printer driver data with keyname",
4085 .usage = "",
4088 .name = "getdriver",
4089 .returntype = RPC_RTYPE_WERROR,
4090 .ntfn = NULL,
4091 .wfn = cmd_spoolss_getdriver,
4092 .table = &ndr_table_spoolss,
4093 .rpc_pipe = NULL,
4094 .description = "Get print driver information",
4095 .usage = "",
4098 .name = "getdriverdir",
4099 .returntype = RPC_RTYPE_WERROR,
4100 .ntfn = NULL,
4101 .wfn = cmd_spoolss_getdriverdir,
4102 .table = &ndr_table_spoolss,
4103 .rpc_pipe = NULL,
4104 .description = "Get print driver upload directory",
4105 .usage = "",
4108 .name = "getdriverpackagepath",
4109 .returntype = RPC_RTYPE_WERROR,
4110 .ntfn = NULL,
4111 .wfn = cmd_spoolss_getdriverpackagepath,
4112 .table = &ndr_table_spoolss,
4113 .rpc_pipe = NULL,
4114 .description = "Get print driver package download directory",
4115 .usage = "",
4118 .name = "getprinter",
4119 .returntype = RPC_RTYPE_WERROR,
4120 .ntfn = NULL,
4121 .wfn = cmd_spoolss_getprinter,
4122 .table = &ndr_table_spoolss,
4123 .rpc_pipe = NULL,
4124 .description = "Get printer info",
4125 .usage = "",
4128 .name = "openprinter",
4129 .returntype = RPC_RTYPE_WERROR,
4130 .ntfn = NULL,
4131 .wfn = cmd_spoolss_open_printer,
4132 .table = &ndr_table_spoolss,
4133 .rpc_pipe = NULL,
4134 .description = "Open printer handle",
4135 .usage = "",
4138 .name = "openprinter_ex",
4139 .returntype = RPC_RTYPE_WERROR,
4140 .ntfn = NULL,
4141 .wfn = cmd_spoolss_open_printer_ex,
4142 .table = &ndr_table_spoolss,
4143 .rpc_pipe = NULL,
4144 .description = "Open printer handle",
4145 .usage = "",
4148 .name = "setdriver",
4149 .returntype = RPC_RTYPE_WERROR,
4150 .ntfn = NULL,
4151 .wfn = cmd_spoolss_setdriver,
4152 .table = &ndr_table_spoolss,
4153 .rpc_pipe = NULL,
4154 .description = "Set printer driver",
4155 .usage = "",
4158 .name = "getprintprocdir",
4159 .returntype = RPC_RTYPE_WERROR,
4160 .ntfn = NULL,
4161 .wfn = cmd_spoolss_getprintprocdir,
4162 .table = &ndr_table_spoolss,
4163 .rpc_pipe = NULL,
4164 .description = "Get print processor directory",
4165 .usage = "",
4168 .name = "addform",
4169 .returntype = RPC_RTYPE_WERROR,
4170 .ntfn = NULL,
4171 .wfn = cmd_spoolss_addform,
4172 .table = &ndr_table_spoolss,
4173 .rpc_pipe = NULL,
4174 .description = "Add form",
4175 .usage = "",
4178 .name = "setform",
4179 .returntype = RPC_RTYPE_WERROR,
4180 .ntfn = NULL,
4181 .wfn = cmd_spoolss_setform,
4182 .table = &ndr_table_spoolss,
4183 .rpc_pipe = NULL,
4184 .description = "Set form",
4185 .usage = "",
4188 .name = "getform",
4189 .returntype = RPC_RTYPE_WERROR,
4190 .ntfn = NULL,
4191 .wfn = cmd_spoolss_getform,
4192 .table = &ndr_table_spoolss,
4193 .rpc_pipe = NULL,
4194 .description = "Get form",
4195 .usage = "",
4198 .name = "deleteform",
4199 .returntype = RPC_RTYPE_WERROR,
4200 .ntfn = NULL,
4201 .wfn = cmd_spoolss_deleteform,
4202 .table = &ndr_table_spoolss,
4203 .rpc_pipe = NULL,
4204 .description = "Delete form",
4205 .usage = "",
4208 .name = "enumforms",
4209 .returntype = RPC_RTYPE_WERROR,
4210 .ntfn = NULL,
4211 .wfn = cmd_spoolss_enum_forms,
4212 .table = &ndr_table_spoolss,
4213 .rpc_pipe = NULL,
4214 .description = "Enumerate forms",
4215 .usage = "",
4218 .name = "setprinter",
4219 .returntype = RPC_RTYPE_WERROR,
4220 .ntfn = NULL,
4221 .wfn = cmd_spoolss_setprinter,
4222 .table = &ndr_table_spoolss,
4223 .rpc_pipe = NULL,
4224 .description = "Set printer comment",
4225 .usage = "",
4228 .name = "setprintername",
4229 .returntype = RPC_RTYPE_WERROR,
4230 .ntfn = NULL,
4231 .wfn = cmd_spoolss_setprintername,
4232 .table = &ndr_table_spoolss,
4233 .rpc_pipe = NULL,
4234 .description = "Set printername",
4235 .usage = "",
4238 .name = "setprinterdata",
4239 .returntype = RPC_RTYPE_WERROR,
4240 .ntfn = NULL,
4241 .wfn = cmd_spoolss_setprinterdata,
4242 .table = &ndr_table_spoolss,
4243 .rpc_pipe = NULL,
4244 .description = "Set REG_SZ printer data",
4245 .usage = "",
4248 .name = "rffpcnex",
4249 .returntype = RPC_RTYPE_WERROR,
4250 .ntfn = NULL,
4251 .wfn = cmd_spoolss_rffpcnex,
4252 .table = &ndr_table_spoolss,
4253 .rpc_pipe = NULL,
4254 .description = "Rffpcnex test",
4255 .usage = "",
4258 .name = "printercmp",
4259 .returntype = RPC_RTYPE_WERROR,
4260 .ntfn = NULL,
4261 .wfn = cmd_spoolss_printercmp,
4262 .table = &ndr_table_spoolss,
4263 .rpc_pipe = NULL,
4264 .description = "Printer comparison test",
4265 .usage = "",
4268 .name = "enumprocs",
4269 .returntype = RPC_RTYPE_WERROR,
4270 .ntfn = NULL,
4271 .wfn = cmd_spoolss_enum_procs,
4272 .table = &ndr_table_spoolss,
4273 .rpc_pipe = NULL,
4274 .description = "Enumerate Print Processors",
4275 .usage = "",
4278 .name = "enumprocdatatypes",
4279 .returntype = RPC_RTYPE_WERROR,
4280 .ntfn = NULL,
4281 .wfn = cmd_spoolss_enum_proc_data_types,
4282 .table = &ndr_table_spoolss,
4283 .rpc_pipe = NULL,
4284 .description = "Enumerate Print Processor Data Types",
4285 .usage = "",
4288 .name = "enummonitors",
4289 .returntype = RPC_RTYPE_WERROR,
4290 .ntfn = NULL,
4291 .wfn = cmd_spoolss_enum_monitors,
4292 .table = &ndr_table_spoolss,
4293 .rpc_pipe = NULL,
4294 .description = "Enumerate Print Monitors",
4295 .usage = "",
4298 .name = "createprinteric",
4299 .returntype = RPC_RTYPE_WERROR,
4300 .ntfn = NULL,
4301 .wfn = cmd_spoolss_create_printer_ic,
4302 .table = &ndr_table_spoolss,
4303 .rpc_pipe = NULL,
4304 .description = "Create Printer IC",
4305 .usage = "",
4308 .name = "playgdiscriptonprinteric",
4309 .returntype = RPC_RTYPE_WERROR,
4310 .ntfn = NULL,
4311 .wfn = cmd_spoolss_play_gdi_script_on_printer_ic,
4312 .table = &ndr_table_spoolss,
4313 .rpc_pipe = NULL,
4314 .description = "Create Printer IC",
4315 .usage = "",
4319 .name = NULL,