s3: smbd: Make extract_snapshot_token() a wrapper for extract_snapshot_token_internal().
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blobdc8bbd161858c0d0d084e1bbd0153e58f4f28387
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 "lib/util/smb_strtox.h"
37 #include "lib/util/string_wrappers.h"
38 #include "lib/cmdline/cmdline.h"
40 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
41 { \
42 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
43 _cli->srv_name_slash, _arg); \
44 W_ERROR_HAVE_NO_MEMORY(_printername); \
48 /**
49 * @file
51 * rpcclient module for SPOOLSS rpc pipe.
53 * This generally just parses and checks command lines, and then calls
54 * a cli_spoolss function.
55 **/
57 /****************************************************************************
58 function to do the mapping between the long architecture name and
59 the short one.
60 ****************************************************************************/
62 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
64 int i=-1;
66 DEBUG(107,("Getting architecture dependent directory\n"));
67 do {
68 i++;
69 } while ( (archi_table[i].long_archi!=NULL ) &&
70 strcasecmp_m(long_archi, archi_table[i].long_archi) );
72 if (archi_table[i].long_archi==NULL) {
73 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
74 return NULL;
77 /* this might be client code - but shouldn't this be an fstrcpy etc? */
80 DEBUGADD(108,("index: [%d]\n", i));
81 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
82 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
84 return archi_table[i].short_archi;
87 /****************************************************************************
88 ****************************************************************************/
90 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
91 TALLOC_CTX *mem_ctx,
92 int argc, const char **argv)
94 WERROR werror;
95 struct policy_handle hnd;
96 uint32_t access_mask = PRINTER_ALL_ACCESS;
97 struct dcerpc_binding_handle *b = cli->binding_handle;
99 if (argc < 2) {
100 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
101 return WERR_OK;
104 if (argc >= 3) {
105 sscanf(argv[2], "%x", &access_mask);
108 /* Open the printer handle */
110 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
111 argv[1],
112 access_mask,
113 &hnd);
114 if (W_ERROR_IS_OK(werror)) {
115 printf("Printer %s opened successfully\n", argv[1]);
116 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
118 if (!W_ERROR_IS_OK(werror)) {
119 printf("Error closing printer handle! (%s)\n",
120 get_dos_error_msg(werror));
124 return werror;
127 /****************************************************************************
128 ****************************************************************************/
130 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
131 TALLOC_CTX *mem_ctx,
132 int argc, const char **argv)
134 WERROR werror;
135 struct policy_handle hnd;
136 uint32_t access_mask = PRINTER_ALL_ACCESS;
137 NTSTATUS status;
138 struct spoolss_DevmodeContainer devmode_ctr;
139 struct dcerpc_binding_handle *b = cli->binding_handle;
141 ZERO_STRUCT(devmode_ctr);
143 if (argc < 2) {
144 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
145 return WERR_OK;
148 if (argc >= 3) {
149 sscanf(argv[2], "%x", &access_mask);
152 /* Open the printer handle */
154 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
155 argv[1],
156 NULL,
157 devmode_ctr,
158 access_mask,
159 &hnd,
160 &werror);
161 if (!NT_STATUS_IS_OK(status)) {
162 return ntstatus_to_werror(status);
164 if (W_ERROR_IS_OK(werror)) {
165 printf("Printer %s opened successfully\n", argv[1]);
166 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
168 if (!W_ERROR_IS_OK(werror)) {
169 printf("Error closing printer handle! (%s)\n",
170 get_dos_error_msg(werror));
174 return werror;
177 /****************************************************************************
178 ****************************************************************************/
180 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
182 if (!r)
183 return;
185 printf("\tprintername:[%s]\n", r->printername);
186 printf("\tservername:[%s]\n", r->servername);
187 printf("\tcjobs:[0x%x]\n", r->cjobs);
188 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
189 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
190 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
191 r->time.day, r->time.day_of_week);
192 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
193 r->time.second, r->time.millisecond);
195 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
196 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
198 printf("\tversion:[0x%x]\n", r->version);
199 printf("\tfree_build:[0x%x]\n", r->free_build);
200 printf("\tspooling:[0x%x]\n", r->spooling);
201 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
202 printf("\tsession_counter:[0x%x]\n", r->session_counter);
203 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
204 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
205 printf("\tjob_error:[0x%x]\n", r->job_error);
206 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
207 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
208 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
209 printf("\tchange_id:[0x%x]\n", r->change_id);
210 printf("\tlast_error: %s\n", win_errstr(r->last_error));
211 printf("\tstatus:[0x%x]\n", r->status);
212 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
213 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
214 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
215 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
216 printf("\tref_ic:[0x%x]\n", r->ref_ic);
217 printf("\treserved2:[0x%x]\n", r->reserved2);
218 printf("\treserved3:[0x%x]\n", r->reserved3);
220 printf("\n");
223 /****************************************************************************
224 ****************************************************************************/
226 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
228 printf("\tflags:[0x%x]\n", r->flags);
229 printf("\tname:[%s]\n", r->name);
230 printf("\tdescription:[%s]\n", r->description);
231 printf("\tcomment:[%s]\n", r->comment);
233 printf("\n");
236 /****************************************************************************
237 ****************************************************************************/
239 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
241 printf("\tservername:[%s]\n", r->servername);
242 printf("\tprintername:[%s]\n", r->printername);
243 printf("\tsharename:[%s]\n", r->sharename);
244 printf("\tportname:[%s]\n", r->portname);
245 printf("\tdrivername:[%s]\n", r->drivername);
246 printf("\tcomment:[%s]\n", r->comment);
247 printf("\tlocation:[%s]\n", r->location);
248 printf("\tsepfile:[%s]\n", r->sepfile);
249 printf("\tprintprocessor:[%s]\n", r->printprocessor);
250 printf("\tdatatype:[%s]\n", r->datatype);
251 printf("\tparameters:[%s]\n", r->parameters);
252 printf("\tattributes:[0x%x]\n", r->attributes);
253 printf("\tpriority:[0x%x]\n", r->priority);
254 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
255 printf("\tstarttime:[0x%x]\n", r->starttime);
256 printf("\tuntiltime:[0x%x]\n", r->untiltime);
257 printf("\tstatus:[0x%x]\n", r->status);
258 printf("\tcjobs:[0x%x]\n", r->cjobs);
259 printf("\taverageppm:[0x%x]\n", r->averageppm);
261 if (r->secdesc)
262 display_sec_desc(r->secdesc);
264 printf("\n");
267 /****************************************************************************
268 ****************************************************************************/
270 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
272 display_sec_desc(r->secdesc);
274 printf("\n");
277 /****************************************************************************
278 ****************************************************************************/
280 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
282 printf("\tservername:[%s]\n", r->servername);
283 printf("\tprintername:[%s]\n", r->printername);
284 printf("\tattributes:[0x%x]\n", r->attributes);
285 printf("\n");
288 /****************************************************************************
289 ****************************************************************************/
291 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
293 printf("\tprintername:[%s]\n", r->printername);
294 printf("\tportname:[%s]\n", r->portname);
295 printf("\tattributes:[0x%x]\n", r->attributes);
296 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
297 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
298 printf("\n");
301 /****************************************************************************
302 ****************************************************************************/
304 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
306 printf("\tstatus:[0x%x]\n", r->status);
307 printf("\n");
310 /****************************************************************************
311 ****************************************************************************/
313 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
315 printf("\tguid:[%s]\n", r->guid);
316 printf("\taction:[0x%x]\n", r->action);
317 printf("\n");
320 /****************************************************************************
321 ****************************************************************************/
323 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
324 TALLOC_CTX *mem_ctx,
325 int argc, const char **argv)
327 WERROR result;
328 uint32_t level = 1;
329 union spoolss_PrinterInfo *info;
330 uint32_t i, count;
331 const char *name;
332 uint32_t flags = PRINTER_ENUM_LOCAL;
334 if (argc > 4) {
335 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
336 return WERR_OK;
339 if (argc >= 2) {
340 level = atoi(argv[1]);
343 if (argc >= 3) {
344 name = argv[2];
345 } else {
346 name = cli->srv_name_slash;
349 if (argc == 4) {
350 flags = atoi(argv[3]);
353 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
354 flags,
355 name,
356 level,
358 &count,
359 &info);
360 if (W_ERROR_IS_OK(result)) {
362 if (!count) {
363 printf ("No printers returned.\n");
364 goto done;
367 for (i = 0; i < count; i++) {
368 switch (level) {
369 case 0:
370 display_print_info0(&info[i].info0);
371 break;
372 case 1:
373 display_print_info1(&info[i].info1);
374 break;
375 case 2:
376 display_print_info2(&info[i].info2);
377 break;
378 case 3:
379 display_print_info3(&info[i].info3);
380 break;
381 case 4:
382 display_print_info4(&info[i].info4);
383 break;
384 case 5:
385 display_print_info5(&info[i].info5);
386 break;
387 case 6:
388 display_print_info6(&info[i].info6);
389 break;
390 default:
391 printf("unknown info level %d\n", level);
392 goto done;
396 done:
398 return result;
401 /****************************************************************************
402 ****************************************************************************/
404 static void display_port_info_1(struct spoolss_PortInfo1 *r)
406 printf("\tPort Name:\t[%s]\n", r->port_name);
409 /****************************************************************************
410 ****************************************************************************/
412 static void display_port_info_2(struct spoolss_PortInfo2 *r)
414 printf("\tPort Name:\t[%s]\n", r->port_name);
415 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
416 printf("\tDescription:\t[%s]\n", r->description);
417 printf("\tPort Type:\t" );
418 if (r->port_type) {
419 int comma = 0; /* hack */
420 printf( "[" );
421 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
422 printf( "Read" );
423 comma = 1;
425 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
426 printf( "%sWrite", comma ? ", " : "" );
427 comma = 1;
429 /* These two have slightly different interpretations
430 on 95/98/ME but I'm disregarding that for now */
431 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
432 printf( "%sRedirected", comma ? ", " : "" );
433 comma = 1;
435 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
436 printf( "%sNet-Attached", comma ? ", " : "" );
438 printf( "]\n" );
439 } else {
440 printf( "[Unset]\n" );
442 printf("\tReserved:\t[%d]\n", r->reserved);
443 printf("\n");
446 /****************************************************************************
447 ****************************************************************************/
449 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
450 TALLOC_CTX *mem_ctx, int argc,
451 const char **argv)
453 WERROR result;
454 uint32_t level = 1;
455 uint32_t count;
456 union spoolss_PortInfo *info;
458 if (argc > 2) {
459 printf("Usage: %s [level]\n", argv[0]);
460 return WERR_OK;
463 if (argc == 2) {
464 level = atoi(argv[1]);
467 /* Enumerate ports */
469 result = rpccli_spoolss_enumports(cli, mem_ctx,
470 cli->srv_name_slash,
471 level,
473 &count,
474 &info);
475 if (W_ERROR_IS_OK(result)) {
476 int i;
478 for (i = 0; i < count; i++) {
479 switch (level) {
480 case 1:
481 display_port_info_1(&info[i].info1);
482 break;
483 case 2:
484 display_port_info_2(&info[i].info2);
485 break;
486 default:
487 printf("unknown info level %d\n", level);
488 break;
493 return result;
496 /****************************************************************************
497 ****************************************************************************/
499 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
500 TALLOC_CTX *mem_ctx,
501 int argc, const char **argv)
503 struct policy_handle pol;
504 WERROR result;
505 NTSTATUS status;
506 uint32_t info_level = 2;
507 union spoolss_PrinterInfo info;
508 struct spoolss_SetPrinterInfoCtr info_ctr;
509 struct spoolss_SetPrinterInfo2 info2;
510 const char *printername, *comment = NULL;
511 struct spoolss_DevmodeContainer devmode_ctr;
512 struct sec_desc_buf secdesc_ctr;
513 struct dcerpc_binding_handle *b = cli->binding_handle;
515 if (argc == 1 || argc > 3) {
516 printf("Usage: %s printername comment\n", argv[0]);
518 return WERR_OK;
521 /* Open a printer handle */
522 if (argc == 3) {
523 comment = argv[2];
526 ZERO_STRUCT(devmode_ctr);
527 ZERO_STRUCT(secdesc_ctr);
529 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
531 /* get a printer handle */
532 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
533 printername,
534 PRINTER_ALL_ACCESS,
535 &pol);
536 if (!W_ERROR_IS_OK(result))
537 goto done;
539 /* Get printer info */
540 result = rpccli_spoolss_getprinter(cli, mem_ctx,
541 &pol,
542 info_level,
544 &info);
545 if (!W_ERROR_IS_OK(result))
546 goto done;
549 /* Modify the comment. */
550 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
551 info2.comment = comment;
553 info_ctr.level = 2;
554 info_ctr.info.info2 = &info2;
556 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
557 &pol,
558 &info_ctr,
559 &devmode_ctr,
560 &secdesc_ctr,
561 0, /* command */
562 &result);
563 if (!NT_STATUS_IS_OK(status)) {
564 result = ntstatus_to_werror(status);
565 goto done;
567 if (W_ERROR_IS_OK(result))
568 printf("Success in setting comment.\n");
570 done:
571 if (is_valid_policy_hnd(&pol)) {
572 WERROR _result;
573 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
576 return result;
579 /****************************************************************************
580 ****************************************************************************/
582 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
583 TALLOC_CTX *mem_ctx,
584 int argc, const char **argv)
586 struct policy_handle pol;
587 WERROR result;
588 NTSTATUS status;
589 uint32_t info_level = 2;
590 union spoolss_PrinterInfo info;
591 const char *printername,
592 *new_printername = NULL;
593 struct spoolss_SetPrinterInfoCtr info_ctr;
594 struct spoolss_SetPrinterInfo2 info2;
595 struct spoolss_DevmodeContainer devmode_ctr;
596 struct sec_desc_buf secdesc_ctr;
597 struct dcerpc_binding_handle *b = cli->binding_handle;
599 ZERO_STRUCT(devmode_ctr);
600 ZERO_STRUCT(secdesc_ctr);
602 if (argc == 1 || argc > 3) {
603 printf("Usage: %s printername new_printername\n", argv[0]);
605 return WERR_OK;
608 /* Open a printer handle */
609 if (argc == 3) {
610 new_printername = argv[2];
613 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
615 /* get a printer handle */
616 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
617 printername,
618 PRINTER_ALL_ACCESS,
619 &pol);
620 if (!W_ERROR_IS_OK(result))
621 goto done;
623 /* Get printer info */
624 result = rpccli_spoolss_getprinter(cli, mem_ctx,
625 &pol,
626 info_level,
628 &info);
629 if (!W_ERROR_IS_OK(result))
630 goto done;
632 /* Modify the printername. */
633 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
634 info2.printername = new_printername;
636 info_ctr.level = 2;
637 info_ctr.info.info2 = &info2;
639 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
640 &pol,
641 &info_ctr,
642 &devmode_ctr,
643 &secdesc_ctr,
644 0, /* command */
645 &result);
646 if (!NT_STATUS_IS_OK(status)) {
647 result = ntstatus_to_werror(status);
648 goto done;
650 if (W_ERROR_IS_OK(result))
651 printf("Success in setting printername.\n");
653 done:
654 if (is_valid_policy_hnd(&pol)) {
655 WERROR _result;
656 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
659 return result;
662 /****************************************************************************
663 ****************************************************************************/
665 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
666 TALLOC_CTX *mem_ctx,
667 int argc, const char **argv)
669 struct policy_handle pol;
670 WERROR result;
671 uint32_t level = 1;
672 const char *printername;
673 union spoolss_PrinterInfo info;
674 struct dcerpc_binding_handle *b = cli->binding_handle;
676 if (argc == 1 || argc > 3) {
677 printf("Usage: %s <printername> [level]\n", argv[0]);
678 return WERR_OK;
681 /* Open a printer handle */
682 if (argc == 3) {
683 level = atoi(argv[2]);
686 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
688 /* get a printer handle */
690 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
691 printername,
692 SEC_FLAG_MAXIMUM_ALLOWED,
693 &pol);
694 if (!W_ERROR_IS_OK(result)) {
695 goto done;
698 /* Get printer info */
700 result = rpccli_spoolss_getprinter(cli, mem_ctx,
701 &pol,
702 level,
704 &info);
705 if (!W_ERROR_IS_OK(result)) {
706 goto done;
709 /* Display printer info */
710 switch (level) {
711 case 0:
712 display_print_info0(&info.info0);
713 break;
714 case 1:
715 display_print_info1(&info.info1);
716 break;
717 case 2:
718 display_print_info2(&info.info2);
719 break;
720 case 3:
721 display_print_info3(&info.info3);
722 break;
723 case 4:
724 display_print_info4(&info.info4);
725 break;
726 case 5:
727 display_print_info5(&info.info5);
728 break;
729 case 6:
730 display_print_info6(&info.info6);
731 break;
732 case 7:
733 display_print_info7(&info.info7);
734 break;
735 default:
736 printf("unknown info level %d\n", level);
737 break;
739 done:
740 if (is_valid_policy_hnd(&pol)) {
741 WERROR _result;
742 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
745 return result;
748 /****************************************************************************
749 ****************************************************************************/
751 static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
753 const char *text = NULL;
755 switch(type) {
756 case REG_DWORD:
757 if (blob.length >= sizeof(uint32_t)) {
758 printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
759 } else {
760 printf("%s: REG_DWORD: <invalid>\n", name);
762 break;
763 case REG_SZ:
764 pull_reg_sz(talloc_tos(), &blob, &text);
765 printf("%s: REG_SZ: %s\n", name, text ? text : "");
766 break;
767 case REG_BINARY: {
768 char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
769 size_t i, len;
770 printf("%s: REG_BINARY:", name);
771 len = strlen(hex);
772 for (i=0; i<len; i++) {
773 if (hex[i] == '\0') {
774 break;
776 if (i%40 == 0) {
777 putchar('\n');
779 putchar(hex[i]);
781 TALLOC_FREE(hex);
782 putchar('\n');
783 break;
785 case REG_MULTI_SZ: {
786 uint32_t i;
787 const char **values;
789 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
790 d_printf("pull_reg_multi_sz failed\n");
791 break;
794 printf("%s: REG_MULTI_SZ: \n", name);
795 for (i=0; values[i] != NULL; i++) {
796 d_printf("%s\n", values[i]);
798 TALLOC_FREE(values);
799 break;
801 default:
802 printf("%s: unknown type %d\n", name, type);
807 /****************************************************************************
808 ****************************************************************************/
810 static void display_printer_data(const char *v,
811 enum winreg_Type type,
812 uint8_t *data,
813 uint32_t length)
815 int i;
816 union spoolss_PrinterData r;
817 DATA_BLOB blob = data_blob_const(data, length);
818 WERROR result;
819 enum ndr_err_code ndr_err;
821 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
822 if (!W_ERROR_IS_OK(result)) {
823 return;
826 switch (type) {
827 case REG_DWORD:
828 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
829 break;
830 case REG_SZ:
831 printf("%s: REG_SZ: %s\n", v, r.string);
832 break;
833 case REG_BINARY: {
834 char *hex = hex_encode_talloc(NULL,
835 r.binary.data, r.binary.length);
836 size_t len;
837 printf("%s: REG_BINARY:", v);
838 len = strlen(hex);
839 for (i=0; i<len; i++) {
840 if (hex[i] == '\0') {
841 break;
843 if (i%40 == 0) {
844 putchar('\n');
846 putchar(hex[i]);
848 TALLOC_FREE(hex);
849 putchar('\n');
850 putchar('\n');
852 if (strequal(v, "OsVersion")) {
853 struct spoolss_OSVersion os;
854 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
855 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
856 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
857 // add output here;
858 printf("OsMajor: %u\n", os.major);
859 printf("OsMinor: %u\n", os.minor);
860 printf("OsBuild: %u\n", os.build);
861 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
864 if (strequal(v, "OsVersionEx")) {
865 struct spoolss_OSVersionEx os;
866 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
867 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
868 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
869 printf("OsMajor: %u\n", os.major);
870 printf("OsMinor: %u\n", os.minor);
871 printf("OsBuild: %u\n", os.build);
872 printf("ServicePackMajor: %u\n", os.service_pack_major);
873 printf("ServicePackMinor: %u\n", os.service_pack_minor);
874 NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
877 break;
879 case REG_MULTI_SZ:
880 printf("%s: REG_MULTI_SZ: ", v);
881 for (i=0; r.string_array[i] != NULL; i++) {
882 printf("%s ", r.string_array[i]);
884 printf("\n");
885 break;
886 default:
887 printf("%s: unknown type 0x%02x:\n", v, type);
888 break;
892 /****************************************************************************
893 ****************************************************************************/
895 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
896 TALLOC_CTX *mem_ctx,
897 int argc, const char **argv)
899 struct policy_handle pol;
900 WERROR result;
901 fstring printername;
902 const char *valuename;
903 enum winreg_Type type;
904 uint8_t *data;
905 uint32_t needed;
906 struct dcerpc_binding_handle *b = cli->binding_handle;
908 if (argc != 3) {
909 printf("Usage: %s <printername> <valuename>\n", argv[0]);
910 printf("<printername> of . queries print server\n");
911 return WERR_OK;
913 valuename = argv[2];
915 /* Open a printer handle */
917 if (strncmp(argv[1], ".", sizeof(".")) == 0)
918 fstrcpy(printername, cli->srv_name_slash);
919 else
920 slprintf(printername, sizeof(printername)-1, "%s\\%s",
921 cli->srv_name_slash, argv[1]);
923 /* get a printer handle */
925 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
926 printername,
927 SEC_FLAG_MAXIMUM_ALLOWED,
928 &pol);
929 if (!W_ERROR_IS_OK(result))
930 goto done;
932 /* Get printer info */
934 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
935 &pol,
936 valuename,
938 &type,
939 &needed,
940 &data);
941 if (!W_ERROR_IS_OK(result))
942 goto done;
944 /* Display printer data */
946 display_printer_data(valuename, type, data, needed);
948 done:
949 if (is_valid_policy_hnd(&pol)) {
950 WERROR _result;
951 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
954 return result;
957 /****************************************************************************
958 ****************************************************************************/
960 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
961 TALLOC_CTX *mem_ctx,
962 int argc, const char **argv)
964 struct policy_handle pol;
965 WERROR result;
966 NTSTATUS status;
967 fstring printername;
968 const char *valuename, *keyname;
970 enum winreg_Type type;
971 uint8_t *data = NULL;
972 uint32_t offered = 0;
973 uint32_t needed;
974 struct dcerpc_binding_handle *b = cli->binding_handle;
976 if (argc != 4) {
977 printf("Usage: %s <printername> <keyname> <valuename>\n",
978 argv[0]);
979 printf("<printername> of . queries print server\n");
980 return WERR_OK;
982 valuename = argv[3];
983 keyname = argv[2];
985 /* Open a printer handle */
987 if (strncmp(argv[1], ".", sizeof(".")) == 0)
988 fstrcpy(printername, cli->srv_name_slash);
989 else
990 slprintf(printername, sizeof(printername)-1, "%s\\%s",
991 cli->srv_name_slash, argv[1]);
993 /* get a printer handle */
995 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
996 printername,
997 SEC_FLAG_MAXIMUM_ALLOWED,
998 &pol);
999 if (!W_ERROR_IS_OK(result))
1000 goto done;
1002 /* Get printer info */
1004 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1005 if (!data) {
1006 goto done;
1009 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1010 &pol,
1011 keyname,
1012 valuename,
1013 &type,
1014 data,
1015 offered,
1016 &needed,
1017 &result);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 result = ntstatus_to_werror(status);
1020 goto done;
1022 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1023 offered = needed;
1024 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1025 if (!data) {
1026 goto done;
1028 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1029 &pol,
1030 keyname,
1031 valuename,
1032 &type,
1033 data,
1034 offered,
1035 &needed,
1036 &result);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 result = ntstatus_to_werror(status);
1041 goto done;
1044 if (!W_ERROR_IS_OK(result))
1045 goto done;
1047 /* Display printer data */
1049 display_printer_data(valuename, type, data, needed);
1052 done:
1053 if (is_valid_policy_hnd(&pol)) {
1054 WERROR _result;
1055 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1058 return result;
1061 /****************************************************************************
1062 ****************************************************************************/
1064 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1066 if (!r) {
1067 return;
1070 printf("Printer Driver Info 1:\n");
1071 printf("\tDriver Name: [%s]\n", r->driver_name);
1072 printf("\n");
1075 /****************************************************************************
1076 ****************************************************************************/
1078 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1080 if (!r) {
1081 return;
1084 printf("Printer Driver Info 2:\n");
1085 printf("\tVersion: [%x]\n", r->version);
1086 printf("\tDriver Name: [%s]\n", r->driver_name);
1087 printf("\tArchitecture: [%s]\n", r->architecture);
1088 printf("\tDriver Path: [%s]\n", r->driver_path);
1089 printf("\tDatafile: [%s]\n", r->data_file);
1090 printf("\tConfigfile: [%s]\n", r->config_file);
1091 printf("\n");
1094 /****************************************************************************
1095 ****************************************************************************/
1097 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1099 int i;
1101 if (!r) {
1102 return;
1105 printf("Printer Driver Info 3:\n");
1106 printf("\tVersion: [%x]\n", r->version);
1107 printf("\tDriver Name: [%s]\n", r->driver_name);
1108 printf("\tArchitecture: [%s]\n", r->architecture);
1109 printf("\tDriver Path: [%s]\n", r->driver_path);
1110 printf("\tDatafile: [%s]\n", r->data_file);
1111 printf("\tConfigfile: [%s]\n", r->config_file);
1112 printf("\tHelpfile: [%s]\n", r->help_file);
1114 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1115 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1118 printf("\tMonitorname: [%s]\n", r->monitor_name);
1119 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1120 printf("\n");
1123 /****************************************************************************
1124 ****************************************************************************/
1126 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1128 int i;
1130 if (!r) {
1131 return;
1134 printf("Printer Driver Info 4:\n");
1135 printf("\tVersion: [%x]\n", r->version);
1136 printf("\tDriver Name: [%s]\n", r->driver_name);
1137 printf("\tArchitecture: [%s]\n", r->architecture);
1138 printf("\tDriver Path: [%s]\n", r->driver_path);
1139 printf("\tDatafile: [%s]\n", r->data_file);
1140 printf("\tConfigfile: [%s]\n", r->config_file);
1141 printf("\tHelpfile: [%s]\n", r->help_file);
1143 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1144 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1147 printf("\tMonitorname: [%s]\n", r->monitor_name);
1148 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1150 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1151 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1153 printf("\n");
1156 /****************************************************************************
1157 ****************************************************************************/
1159 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1161 if (!r) {
1162 return;
1165 printf("Printer Driver Info 5:\n");
1166 printf("\tVersion: [%x]\n", r->version);
1167 printf("\tDriver Name: [%s]\n", r->driver_name);
1168 printf("\tArchitecture: [%s]\n", r->architecture);
1169 printf("\tDriver Path: [%s]\n", r->driver_path);
1170 printf("\tDatafile: [%s]\n", r->data_file);
1171 printf("\tConfigfile: [%s]\n", r->config_file);
1172 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1173 printf("\tConfig Version: [0x%x]\n", r->config_version);
1174 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1175 printf("\n");
1178 /****************************************************************************
1179 ****************************************************************************/
1181 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1183 int i;
1185 if (!r) {
1186 return;
1189 printf("Printer Driver Info 6:\n");
1190 printf("\tVersion: [%x]\n", r->version);
1191 printf("\tDriver Name: [%s]\n", r->driver_name);
1192 printf("\tArchitecture: [%s]\n", r->architecture);
1193 printf("\tDriver Path: [%s]\n", r->driver_path);
1194 printf("\tDatafile: [%s]\n", r->data_file);
1195 printf("\tConfigfile: [%s]\n", r->config_file);
1196 printf("\tHelpfile: [%s]\n", r->help_file);
1198 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1199 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1202 printf("\tMonitorname: [%s]\n", r->monitor_name);
1203 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1205 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1206 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1209 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1210 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1211 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1212 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1213 printf("\tHardware ID: [%s]\n", r->hardware_id);
1214 printf("\tProvider: [%s]\n", r->provider);
1216 printf("\n");
1219 /****************************************************************************
1220 ****************************************************************************/
1222 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1224 int i;
1226 if (!r) {
1227 return;
1230 printf("Printer Driver Info 8:\n");
1231 printf("\tVersion: [%x]\n", r->version);
1232 printf("\tDriver Name: [%s]\n", r->driver_name);
1233 printf("\tArchitecture: [%s]\n", r->architecture);
1234 printf("\tDriver Path: [%s]\n", r->driver_path);
1235 printf("\tDatafile: [%s]\n", r->data_file);
1236 printf("\tConfigfile: [%s]\n", r->config_file);
1237 printf("\tHelpfile: [%s]\n", r->help_file);
1238 printf("\tMonitorname: [%s]\n", r->monitor_name);
1239 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1241 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1242 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1245 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1246 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1249 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1250 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1251 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1252 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1253 printf("\tHardware ID: [%s]\n", r->hardware_id);
1254 printf("\tProvider: [%s]\n", r->provider);
1255 printf("\tPrint Processor: [%s]\n", r->print_processor);
1256 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1257 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1258 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1260 printf("\tInf Path: [%s]\n", r->inf_path);
1261 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1262 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1263 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1265 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1266 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1267 (long long unsigned int)r->min_inbox_driver_ver_version);
1269 printf("\n");
1272 /****************************************************************************
1273 ****************************************************************************/
1275 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1276 TALLOC_CTX *mem_ctx,
1277 int argc, const char **argv)
1279 struct policy_handle pol;
1280 WERROR werror;
1281 uint32_t level = 3;
1282 const char *printername;
1283 uint32_t i;
1284 bool success = false;
1285 union spoolss_DriverInfo info;
1286 uint32_t server_major_version;
1287 uint32_t server_minor_version;
1288 struct dcerpc_binding_handle *b = cli->binding_handle;
1290 if ((argc == 1) || (argc > 3)) {
1291 printf("Usage: %s <printername> [level]\n", argv[0]);
1292 return WERR_OK;
1295 /* get the arguments need to open the printer handle */
1297 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1299 if (argc == 3) {
1300 level = atoi(argv[2]);
1303 /* Open a printer handle */
1305 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1306 printername,
1307 PRINTER_ACCESS_USE,
1308 &pol);
1309 if (!W_ERROR_IS_OK(werror)) {
1310 printf("Error opening printer handle for %s!\n", printername);
1311 return werror;
1314 /* loop through and print driver info level for each architecture */
1316 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1318 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1319 &pol,
1320 archi_table[i].long_archi,
1321 level,
1322 0, /* offered */
1323 archi_table[i].version,
1325 &info,
1326 &server_major_version,
1327 &server_minor_version);
1328 if (!W_ERROR_IS_OK(werror)) {
1329 continue;
1332 /* need at least one success */
1334 success = true;
1336 printf("\n[%s]\n", archi_table[i].long_archi);
1338 switch (level) {
1339 case 1:
1340 display_print_driver1(&info.info1);
1341 break;
1342 case 2:
1343 display_print_driver2(&info.info2);
1344 break;
1345 case 3:
1346 display_print_driver3(&info.info3);
1347 break;
1348 case 4:
1349 display_print_driver4(&info.info4);
1350 break;
1351 case 5:
1352 display_print_driver5(&info.info5);
1353 break;
1354 case 6:
1355 display_print_driver6(&info.info6);
1356 break;
1357 case 8:
1358 display_print_driver8(&info.info8);
1359 break;
1360 default:
1361 printf("unknown info level %d\n", level);
1362 break;
1366 /* Cleanup */
1368 if (is_valid_policy_hnd(&pol)) {
1369 WERROR _result;
1370 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1373 if (success) {
1374 werror = WERR_OK;
1377 return werror;
1380 /****************************************************************************
1381 ****************************************************************************/
1383 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1384 TALLOC_CTX *mem_ctx,
1385 const char *architecture,
1386 uint32_t level)
1388 WERROR werror;
1389 uint32_t count = 0;
1390 union spoolss_DriverInfo *info = NULL;
1391 uint32_t j;
1393 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1394 cli->srv_name_slash,
1395 architecture,
1396 level,
1398 &count,
1399 &info);
1401 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1402 printf("Server does not support environment [%s]\n",
1403 architecture);
1404 return WERR_OK;
1407 if (count == 0) {
1408 return WERR_OK;
1411 if (!W_ERROR_IS_OK(werror)) {
1412 printf("Error getting driver for environment [%s] - %s\n",
1413 architecture, win_errstr(werror));
1414 return werror;
1417 printf("\n[%s]\n", architecture);
1419 switch (level) {
1420 case 1:
1421 for (j=0; j < count; j++) {
1422 display_print_driver1(&info[j].info1);
1424 break;
1425 case 2:
1426 for (j=0; j < count; j++) {
1427 display_print_driver2(&info[j].info2);
1429 break;
1430 case 3:
1431 for (j=0; j < count; j++) {
1432 display_print_driver3(&info[j].info3);
1434 break;
1435 case 4:
1436 for (j=0; j < count; j++) {
1437 display_print_driver4(&info[j].info4);
1439 break;
1440 case 5:
1441 for (j=0; j < count; j++) {
1442 display_print_driver5(&info[j].info5);
1444 break;
1445 case 6:
1446 for (j=0; j < count; j++) {
1447 display_print_driver6(&info[j].info6);
1449 break;
1450 case 8:
1451 for (j=0; j < count; j++) {
1452 display_print_driver8(&info[j].info8);
1454 break;
1455 default:
1456 printf("unknown info level %d\n", level);
1457 return WERR_INVALID_LEVEL;
1460 return werror;
1463 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1464 TALLOC_CTX *mem_ctx,
1465 int argc, const char **argv)
1467 WERROR werror = WERR_OK;
1468 uint32_t level = 1;
1469 uint32_t i;
1470 const char *architecture = NULL;
1472 if (argc > 3) {
1473 printf("Usage: enumdrivers [level] [architecture]\n");
1474 return WERR_OK;
1477 if (argc >= 2) {
1478 level = atoi(argv[1]);
1481 if (argc == 3) {
1482 architecture = argv[2];
1485 if (architecture) {
1486 return enum_driver_by_architecture(cli, mem_ctx,
1487 architecture,
1488 level);
1491 /* loop through and print driver info level for each architecture */
1492 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1493 /* check to see if we already asked for this architecture string */
1495 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1496 continue;
1499 werror = enum_driver_by_architecture(cli, mem_ctx,
1500 archi_table[i].long_archi,
1501 level);
1502 if (!W_ERROR_IS_OK(werror)) {
1503 break;
1507 return werror;
1510 /****************************************************************************
1511 ****************************************************************************/
1513 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1515 printf("\tDirectory Name:[%s]\n", r->directory_name);
1518 /****************************************************************************
1519 ****************************************************************************/
1521 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1522 TALLOC_CTX *mem_ctx,
1523 int argc, const char **argv)
1525 WERROR result;
1526 NTSTATUS status;
1527 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1528 DATA_BLOB buffer;
1529 uint32_t offered;
1530 union spoolss_DriverDirectoryInfo info;
1531 uint32_t needed;
1532 struct dcerpc_binding_handle *b = cli->binding_handle;
1534 if (argc > 2) {
1535 printf("Usage: %s [environment]\n", argv[0]);
1536 return WERR_OK;
1539 /* Get the arguments need to open the printer handle */
1541 if (argc == 2) {
1542 env = argv[1];
1545 /* Get the directory. Only use Info level 1 */
1547 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1548 cli->srv_name_slash,
1549 env,
1551 NULL, /* buffer */
1552 0, /* offered */
1553 NULL, /* info */
1554 &needed,
1555 &result);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 return ntstatus_to_werror(status);
1559 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1560 offered = needed;
1561 buffer = data_blob_talloc_zero(mem_ctx, needed);
1563 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1564 cli->srv_name_slash,
1565 env,
1567 &buffer,
1568 offered,
1569 &info,
1570 &needed,
1571 &result);
1572 if (!NT_STATUS_IS_OK(status)) {
1573 return ntstatus_to_werror(status);
1577 if (W_ERROR_IS_OK(result)) {
1578 display_printdriverdir_1(&info.info1);
1581 return result;
1584 /****************************************************************************
1585 ****************************************************************************/
1587 static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
1588 TALLOC_CTX *mem_ctx,
1589 int argc, const char **argv)
1591 HRESULT hresult;
1592 NTSTATUS status;
1593 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1594 uint32_t offered;
1595 uint32_t needed;
1596 struct dcerpc_binding_handle *b = cli->binding_handle;
1597 const char *package_id = "";
1598 const char *cab = NULL;
1600 if (argc > 4) {
1601 printf("Usage: %s [environment] [package_id]\n", argv[0]);
1602 return WERR_OK;
1605 /* Get the arguments need to open the printer handle */
1607 if (argc >= 2) {
1608 env = argv[1];
1611 if (argc == 3) {
1612 package_id = argv[2];
1615 offered = 1;
1616 cab = talloc_zero_array(mem_ctx, char, offered);
1617 if (cab == NULL) {
1618 return WERR_NOT_ENOUGH_MEMORY;
1620 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1621 cli->srv_name_slash,
1622 env,
1623 NULL,
1624 package_id,
1625 cab,
1626 offered,
1627 &needed,
1628 &hresult);
1629 if (!NT_STATUS_IS_OK(status)) {
1630 return ntstatus_to_werror(status);
1633 if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
1634 offered = needed;
1635 cab = talloc_zero_array(mem_ctx, char, offered);
1636 if (cab == NULL) {
1637 return WERR_NOT_ENOUGH_MEMORY;
1639 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1640 cli->srv_name_slash,
1641 env,
1642 NULL,
1643 package_id,
1644 cab,
1645 offered,
1646 &needed,
1647 &hresult);
1648 if (!NT_STATUS_IS_OK(status)) {
1649 return ntstatus_to_werror(status);
1653 return W_ERROR(WIN32_FROM_HRESULT(hresult));
1657 /****************************************************************************
1658 ****************************************************************************/
1660 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1661 struct spoolss_AddDriverInfo3 *info,
1662 const char *arch)
1665 int i;
1667 for (i=0; archi_table[i].long_archi != NULL; i++)
1669 if (strcmp(arch, archi_table[i].short_archi) == 0)
1671 info->version = archi_table[i].version;
1672 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1673 break;
1677 if (archi_table[i].long_archi == NULL)
1679 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1682 return;
1686 /**************************************************************************
1687 wrapper for strtok to get the next parameter from a delimited list.
1688 Needed to handle the empty parameter string denoted by "NULL"
1689 *************************************************************************/
1691 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1692 const char *delim, const char **dest,
1693 char **saveptr)
1695 char *ptr;
1697 /* get the next token */
1698 ptr = strtok_r(str, delim, saveptr);
1700 /* a string of 'NULL' is used to represent an empty
1701 parameter because two consecutive delimiters
1702 will not return an empty string. See man strtok(3)
1703 for details */
1704 if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1705 ptr = NULL;
1708 if (dest != NULL) {
1709 *dest = talloc_strdup(mem_ctx, ptr);
1712 return ptr;
1715 /********************************************************************************
1716 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1717 string in the form of
1718 <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1719 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1720 <Default Data Type>:<Comma Separated list of Files>
1721 *******************************************************************************/
1723 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1724 char *args)
1726 char *str, *str2;
1727 size_t count = 0;
1728 char *saveptr = NULL;
1729 struct spoolss_StringArray *deps;
1730 const char **file_array = NULL;
1731 int i;
1733 /* fill in the UNISTR fields */
1734 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1735 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1736 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1737 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1738 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1739 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1740 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1742 /* <Comma Separated List of Dependent Files> */
1743 /* save the beginning of the string */
1744 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1745 str = str2;
1747 /* begin to strip out each filename */
1748 str = strtok_r(str, ",", &saveptr);
1750 /* no dependent files, we are done */
1751 if (!str) {
1752 return true;
1755 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1756 if (!deps) {
1757 return false;
1760 while (str != NULL) {
1761 bool ok;
1762 ok = add_string_to_array(deps, str, &file_array, &count);
1763 if (!ok) {
1764 return false;
1766 str = strtok_r(NULL, ",", &saveptr);
1769 deps->string = talloc_zero_array(deps, const char *, count + 1);
1770 if (!deps->string) {
1771 return false;
1774 for (i=0; i < count; i++) {
1775 deps->string[i] = file_array[i];
1778 r->dependent_files = deps;
1780 return true;
1783 /****************************************************************************
1784 ****************************************************************************/
1786 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1787 TALLOC_CTX *mem_ctx,
1788 int argc, const char **argv)
1790 WERROR result;
1791 NTSTATUS status;
1792 uint32_t level = 3;
1793 struct spoolss_AddDriverInfoCtr info_ctr;
1794 struct spoolss_AddDriverInfo3 info3;
1795 const char *arch;
1796 char *driver_args;
1797 struct dcerpc_binding_handle *b = cli->binding_handle;
1799 /* parse the command arguments */
1800 if (argc != 3 && argc != 4)
1802 printf ("Usage: %s <Environment> \\\n", argv[0]);
1803 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1804 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1805 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1806 printf ("\t[version]\n");
1808 return WERR_OK;
1811 /* Fill in the spoolss_AddDriverInfo3 struct */
1812 ZERO_STRUCT(info3);
1814 arch = cmd_spoolss_get_short_archi(argv[1]);
1815 if (!arch) {
1816 printf ("Error Unknown architecture [%s]\n", argv[1]);
1817 return WERR_INVALID_PARAMETER;
1820 set_drv_info_3_env(mem_ctx, &info3, arch);
1822 driver_args = talloc_strdup( mem_ctx, argv[2] );
1823 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1825 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1826 return WERR_INVALID_PARAMETER;
1829 /* if printer driver version specified, override the default version
1830 * used by the architecture. This allows installation of Windows
1831 * 2000 (version 3) printer drivers. */
1832 if (argc == 4)
1834 info3.version = atoi(argv[3]);
1838 info_ctr.level = level;
1839 info_ctr.info.info3 = &info3;
1841 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1842 cli->srv_name_slash,
1843 &info_ctr,
1844 &result);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 return ntstatus_to_werror(status);
1848 if (W_ERROR_IS_OK(result)) {
1849 printf ("Printer Driver %s successfully installed.\n",
1850 info3.driver_name);
1853 return result;
1857 /****************************************************************************
1858 ****************************************************************************/
1860 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1861 TALLOC_CTX *mem_ctx,
1862 int argc, const char **argv)
1864 WERROR result;
1865 struct spoolss_SetPrinterInfoCtr info_ctr;
1866 struct spoolss_SetPrinterInfo2 info2;
1868 /* parse the command arguments */
1869 if (argc != 5)
1871 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1872 return WERR_OK;
1875 /* Fill in the DRIVER_INFO_2 struct */
1876 ZERO_STRUCT(info2);
1878 info2.printername = argv[1];
1879 info2.drivername = argv[3];
1880 info2.sharename = argv[2];
1881 info2.portname = argv[4];
1882 info2.comment = "Created by rpcclient";
1883 info2.printprocessor = "winprint";
1884 info2.datatype = "RAW";
1885 info2.devmode_ptr = 0;
1886 info2.secdesc_ptr = 0;
1887 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1888 info2.priority = 0;
1889 info2.defaultpriority = 0;
1890 info2.starttime = 0;
1891 info2.untiltime = 0;
1893 /* These three fields must not be used by AddPrinter()
1894 as defined in the MS Platform SDK documentation..
1895 --jerry
1896 info2.status = 0;
1897 info2.cjobs = 0;
1898 info2.averageppm = 0;
1901 info_ctr.level = 2;
1902 info_ctr.info.info2 = &info2;
1904 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1905 &info_ctr);
1906 if (W_ERROR_IS_OK(result))
1907 printf ("Printer %s successfully installed.\n", argv[1]);
1909 return result;
1912 /****************************************************************************
1913 ****************************************************************************/
1915 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1916 TALLOC_CTX *mem_ctx,
1917 int argc, const char **argv)
1919 struct policy_handle pol;
1920 WERROR result;
1921 NTSTATUS status;
1922 uint32_t level = 2;
1923 const char *printername;
1924 union spoolss_PrinterInfo info;
1925 struct spoolss_SetPrinterInfoCtr info_ctr;
1926 struct spoolss_SetPrinterInfo2 info2;
1927 struct spoolss_DevmodeContainer devmode_ctr;
1928 struct sec_desc_buf secdesc_ctr;
1929 struct dcerpc_binding_handle *b = cli->binding_handle;
1931 ZERO_STRUCT(devmode_ctr);
1932 ZERO_STRUCT(secdesc_ctr);
1934 /* parse the command arguments */
1935 if (argc != 3)
1937 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1938 return WERR_OK;
1941 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1943 /* Get a printer handle */
1945 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1946 printername,
1947 PRINTER_ALL_ACCESS,
1948 &pol);
1949 if (!W_ERROR_IS_OK(result))
1950 goto done;
1952 /* Get printer info */
1954 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1955 &pol,
1956 level,
1958 &info);
1959 if (!W_ERROR_IS_OK(result)) {
1960 printf ("Unable to retrieve printer information!\n");
1961 goto done;
1964 /* Set the printer driver */
1966 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1967 info2.drivername = argv[2];
1969 info_ctr.level = 2;
1970 info_ctr.info.info2 = &info2;
1972 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1973 &pol,
1974 &info_ctr,
1975 &devmode_ctr,
1976 &secdesc_ctr,
1977 0, /* command */
1978 &result);
1979 if (!NT_STATUS_IS_OK(status)) {
1980 result = ntstatus_to_werror(status);
1981 goto done;
1983 if (!W_ERROR_IS_OK(result)) {
1984 printf("SetPrinter call failed!\n");
1985 goto done;
1988 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1990 done:
1991 /* Cleanup */
1993 if (is_valid_policy_hnd(&pol)) {
1994 WERROR _result;
1995 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1998 return result;
2002 /****************************************************************************
2003 ****************************************************************************/
2005 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
2006 TALLOC_CTX *mem_ctx,
2007 int argc, const char **argv)
2009 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
2010 NTSTATUS status;
2011 struct dcerpc_binding_handle *b = cli->binding_handle;
2013 int i;
2014 int vers = -1;
2016 const char *arch = NULL;
2017 uint32_t delete_flags = 0;
2019 /* parse the command arguments */
2020 if (argc < 2 || argc > 5) {
2021 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
2022 return WERR_OK;
2025 if (argc >= 3)
2026 arch = argv[2];
2027 if (argc >= 4) {
2028 vers = atoi(argv[3]);
2029 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
2031 if (argc == 5)
2032 delete_flags = atoi(argv[4]);
2034 /* delete the driver for all architectures */
2035 for (i=0; archi_table[i].long_archi; i++) {
2037 if (arch && !strequal(archi_table[i].long_archi, arch))
2038 continue;
2040 if (vers >= 0 && archi_table[i].version != vers)
2041 continue;
2043 /* make the call to remove the driver */
2044 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
2045 cli->srv_name_slash,
2046 archi_table[i].long_archi,
2047 argv[1],
2048 delete_flags,
2049 archi_table[i].version,
2050 &result);
2051 if (!NT_STATUS_IS_OK(status)) {
2052 return ntstatus_to_werror(status);
2054 if ( !W_ERROR_IS_OK(result) )
2056 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2057 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2058 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
2061 else
2063 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
2064 archi_table[i].long_archi, archi_table[i].version);
2065 ret = WERR_OK;
2069 return ret;
2073 /****************************************************************************
2074 ****************************************************************************/
2076 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2077 TALLOC_CTX *mem_ctx,
2078 int argc, const char **argv)
2080 WERROR result = WERR_OK;
2081 NTSTATUS status;
2082 int i;
2083 struct dcerpc_binding_handle *b = cli->binding_handle;
2085 /* parse the command arguments */
2086 if (argc != 2) {
2087 printf ("Usage: %s <driver>\n", argv[0]);
2088 return WERR_OK;
2091 /* delete the driver for all architectures */
2092 for (i=0; archi_table[i].long_archi; i++) {
2093 result = WERR_OK;
2095 /* make the call to remove the driver */
2096 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2097 cli->srv_name_slash,
2098 archi_table[i].long_archi,
2099 argv[1],
2100 &result);
2101 if (!NT_STATUS_IS_OK(status)) {
2102 result = ntstatus_to_werror(status);
2103 continue;
2105 if ( !W_ERROR_IS_OK(result) ) {
2106 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2107 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2108 argv[1], archi_table[i].long_archi,
2109 win_errstr(result));
2111 } else {
2112 printf ("Driver %s removed for arch [%s].\n", argv[1],
2113 archi_table[i].long_archi);
2117 return result;
2120 /****************************************************************************
2121 ****************************************************************************/
2123 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2124 TALLOC_CTX *mem_ctx,
2125 int argc, const char **argv)
2127 WERROR result;
2128 NTSTATUS status;
2129 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2130 DATA_BLOB buffer;
2131 uint32_t offered;
2132 union spoolss_PrintProcessorDirectoryInfo info;
2133 uint32_t needed;
2134 struct dcerpc_binding_handle *b = cli->binding_handle;
2136 /* parse the command arguments */
2137 if (argc > 2) {
2138 printf ("Usage: %s [environment]\n", argv[0]);
2139 return WERR_OK;
2142 if (argc == 2) {
2143 environment = argv[1];
2146 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2147 cli->srv_name_slash,
2148 environment,
2150 NULL, /* buffer */
2151 0, /* offered */
2152 NULL, /* info */
2153 &needed,
2154 &result);
2155 if (!NT_STATUS_IS_OK(status)) {
2156 return ntstatus_to_werror(status);
2158 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2159 offered = needed;
2160 buffer = data_blob_talloc_zero(mem_ctx, needed);
2162 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2163 cli->srv_name_slash,
2164 environment,
2166 &buffer,
2167 offered,
2168 &info,
2169 &needed,
2170 &result);
2171 if (!NT_STATUS_IS_OK(status)) {
2172 return ntstatus_to_werror(status);
2176 if (W_ERROR_IS_OK(result)) {
2177 printf("%s\n", info.info1.directory_name);
2180 return result;
2183 /****************************************************************************
2184 ****************************************************************************/
2186 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2187 int argc, const char **argv)
2189 struct policy_handle handle;
2190 WERROR werror;
2191 NTSTATUS status;
2192 const char *printername;
2193 struct spoolss_AddFormInfoCtr info_ctr;
2194 struct spoolss_AddFormInfo1 info1;
2195 struct spoolss_AddFormInfo2 info2;
2196 uint32_t level = 1;
2197 struct dcerpc_binding_handle *b = cli->binding_handle;
2199 /* Parse the command arguments */
2201 if (argc < 3 || argc > 5) {
2202 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2203 return WERR_OK;
2206 /* Get a printer handle */
2208 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2210 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2211 printername,
2212 PRINTER_ALL_ACCESS,
2213 &handle);
2214 if (!W_ERROR_IS_OK(werror))
2215 goto done;
2217 /* Dummy up some values for the form data */
2219 if (argc == 4) {
2220 level = atoi(argv[3]);
2223 switch (level) {
2224 case 1:
2225 info1.flags = SPOOLSS_FORM_USER;
2226 info1.form_name = argv[2];
2227 info1.size.width = 100;
2228 info1.size.height = 100;
2229 info1.area.left = 0;
2230 info1.area.top = 10;
2231 info1.area.right = 20;
2232 info1.area.bottom = 30;
2234 info_ctr.level = 1;
2235 info_ctr.info.info1 = &info1;
2237 break;
2238 case 2:
2239 info2.flags = SPOOLSS_FORM_USER;
2240 info2.form_name = argv[2];
2241 info2.size.width = 100;
2242 info2.size.height = 100;
2243 info2.area.left = 0;
2244 info2.area.top = 10;
2245 info2.area.right = 20;
2246 info2.area.bottom = 30;
2247 info2.keyword = argv[2];
2248 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2249 info2.mui_dll = NULL;
2250 info2.ressource_id = 0;
2251 info2.display_name = argv[2];
2252 info2.lang_id = 0;
2254 info_ctr.level = 2;
2255 info_ctr.info.info2 = &info2;
2257 break;
2258 default:
2259 werror = WERR_INVALID_PARAMETER;
2260 goto done;
2263 /* Add the form */
2265 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2266 &handle,
2267 &info_ctr,
2268 &werror);
2269 if (!NT_STATUS_IS_OK(status)) {
2270 werror = ntstatus_to_werror(status);
2271 goto done;
2273 done:
2274 if (is_valid_policy_hnd(&handle)) {
2275 WERROR _result;
2276 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2279 return werror;
2282 /****************************************************************************
2283 ****************************************************************************/
2285 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2286 int argc, const char **argv)
2288 struct policy_handle handle;
2289 WERROR werror;
2290 NTSTATUS status;
2291 const char *printername;
2292 struct spoolss_AddFormInfoCtr info_ctr;
2293 struct spoolss_AddFormInfo1 info1;
2294 struct dcerpc_binding_handle *b = cli->binding_handle;
2296 /* Parse the command arguments */
2298 if (argc != 3) {
2299 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2300 return WERR_OK;
2303 /* Get a printer handle */
2305 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2307 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2308 printername,
2309 SEC_FLAG_MAXIMUM_ALLOWED,
2310 &handle);
2311 if (!W_ERROR_IS_OK(werror))
2312 goto done;
2314 /* Dummy up some values for the form data */
2316 info1.flags = SPOOLSS_FORM_PRINTER;
2317 info1.size.width = 100;
2318 info1.size.height = 100;
2319 info1.area.left = 0;
2320 info1.area.top = 1000;
2321 info1.area.right = 2000;
2322 info1.area.bottom = 3000;
2323 info1.form_name = argv[2];
2325 info_ctr.info.info1 = &info1;
2326 info_ctr.level = 1;
2328 /* Set the form */
2330 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2331 &handle,
2332 argv[2],
2333 &info_ctr,
2334 &werror);
2335 if (!NT_STATUS_IS_OK(status)) {
2336 werror = ntstatus_to_werror(status);
2337 goto done;
2339 done:
2340 if (is_valid_policy_hnd(&handle)) {
2341 WERROR _result;
2342 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2345 return werror;
2348 /****************************************************************************
2349 ****************************************************************************/
2351 static const char *get_form_flag(int form_flag)
2353 switch (form_flag) {
2354 case SPOOLSS_FORM_USER:
2355 return "FORM_USER";
2356 case SPOOLSS_FORM_BUILTIN:
2357 return "FORM_BUILTIN";
2358 case SPOOLSS_FORM_PRINTER:
2359 return "FORM_PRINTER";
2360 default:
2361 return "unknown";
2365 /****************************************************************************
2366 ****************************************************************************/
2368 static void display_form_info1(struct spoolss_FormInfo1 *r)
2370 printf("%s\n" \
2371 "\tflag: %s (%d)\n" \
2372 "\twidth: %d, length: %d\n" \
2373 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2374 r->form_name, get_form_flag(r->flags), r->flags,
2375 r->size.width, r->size.height,
2376 r->area.left, r->area.right,
2377 r->area.top, r->area.bottom);
2380 /****************************************************************************
2381 ****************************************************************************/
2383 static void display_form_info2(struct spoolss_FormInfo2 *r)
2385 printf("%s\n" \
2386 "\tflag: %s (%d)\n" \
2387 "\twidth: %d, length: %d\n" \
2388 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2389 r->form_name, get_form_flag(r->flags), r->flags,
2390 r->size.width, r->size.height,
2391 r->area.left, r->area.right,
2392 r->area.top, r->area.bottom);
2393 printf("\tkeyword: %s\n", r->keyword);
2394 printf("\tstring_type: 0x%08x\n", r->string_type);
2395 printf("\tmui_dll: %s\n", r->mui_dll);
2396 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2397 printf("\tdisplay_name: %s\n", r->display_name);
2398 printf("\tlang_id: %d\n", r->lang_id);
2399 printf("\n");
2402 /****************************************************************************
2403 ****************************************************************************/
2405 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2406 int argc, const char **argv)
2408 struct policy_handle handle;
2409 WERROR werror;
2410 NTSTATUS status;
2411 const char *printername;
2412 DATA_BLOB buffer;
2413 uint32_t offered = 0;
2414 union spoolss_FormInfo info;
2415 uint32_t needed;
2416 uint32_t level = 1;
2417 struct dcerpc_binding_handle *b = cli->binding_handle;
2419 /* Parse the command arguments */
2421 if (argc < 3 || argc > 5) {
2422 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2423 return WERR_OK;
2426 /* Get a printer handle */
2428 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2430 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2431 printername,
2432 SEC_FLAG_MAXIMUM_ALLOWED,
2433 &handle);
2434 if (!W_ERROR_IS_OK(werror))
2435 goto done;
2437 if (argc == 4) {
2438 level = atoi(argv[3]);
2441 /* Get the form */
2443 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2444 &handle,
2445 argv[2],
2446 level,
2447 NULL,
2448 offered,
2449 &info,
2450 &needed,
2451 &werror);
2452 if (!NT_STATUS_IS_OK(status)) {
2453 werror = ntstatus_to_werror(status);
2454 goto done;
2456 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2457 buffer = data_blob_talloc_zero(mem_ctx, needed);
2458 offered = needed;
2459 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2460 &handle,
2461 argv[2],
2462 level,
2463 &buffer,
2464 offered,
2465 &info,
2466 &needed,
2467 &werror);
2468 if (!NT_STATUS_IS_OK(status)) {
2469 werror = ntstatus_to_werror(status);
2470 goto done;
2474 if (!W_ERROR_IS_OK(werror)) {
2475 goto done;
2478 switch (level) {
2479 case 1:
2480 display_form_info1(&info.info1);
2481 break;
2482 case 2:
2483 display_form_info2(&info.info2);
2484 break;
2487 done:
2488 if (is_valid_policy_hnd(&handle)) {
2489 WERROR _result;
2490 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2493 return werror;
2496 /****************************************************************************
2497 ****************************************************************************/
2499 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2500 TALLOC_CTX *mem_ctx, int argc,
2501 const char **argv)
2503 struct policy_handle handle;
2504 WERROR werror;
2505 NTSTATUS status;
2506 const char *printername;
2507 struct dcerpc_binding_handle *b = cli->binding_handle;
2509 /* Parse the command arguments */
2511 if (argc != 3) {
2512 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2513 return WERR_OK;
2516 /* Get a printer handle */
2518 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2520 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2521 printername,
2522 SEC_FLAG_MAXIMUM_ALLOWED,
2523 &handle);
2524 if (!W_ERROR_IS_OK(werror))
2525 goto done;
2527 /* Delete the form */
2529 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2530 &handle,
2531 argv[2],
2532 &werror);
2533 if (!NT_STATUS_IS_OK(status)) {
2534 werror = ntstatus_to_werror(status);
2535 goto done;
2538 done:
2539 if (is_valid_policy_hnd(&handle)) {
2540 WERROR _result;
2541 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2544 return werror;
2547 /****************************************************************************
2548 ****************************************************************************/
2550 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2551 TALLOC_CTX *mem_ctx, int argc,
2552 const char **argv)
2554 struct policy_handle handle;
2555 WERROR werror;
2556 const char *printername;
2557 uint32_t num_forms, level = 1, i;
2558 union spoolss_FormInfo *forms;
2559 struct dcerpc_binding_handle *b = cli->binding_handle;
2561 /* Parse the command arguments */
2563 if (argc < 2 || argc > 4) {
2564 printf ("Usage: %s <printer> [level]\n", argv[0]);
2565 return WERR_OK;
2568 /* Get a printer handle */
2570 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2572 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2573 printername,
2574 SEC_FLAG_MAXIMUM_ALLOWED,
2575 &handle);
2576 if (!W_ERROR_IS_OK(werror))
2577 goto done;
2579 if (argc == 3) {
2580 level = atoi(argv[2]);
2583 /* Enumerate forms */
2585 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2586 &handle,
2587 level,
2589 &num_forms,
2590 &forms);
2592 if (!W_ERROR_IS_OK(werror))
2593 goto done;
2595 /* Display output */
2597 for (i = 0; i < num_forms; i++) {
2598 switch (level) {
2599 case 1:
2600 display_form_info1(&forms[i].info1);
2601 break;
2602 case 2:
2603 display_form_info2(&forms[i].info2);
2604 break;
2608 done:
2609 if (is_valid_policy_hnd(&handle)) {
2610 WERROR _result;
2611 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2614 return werror;
2617 /****************************************************************************
2618 ****************************************************************************/
2620 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2621 TALLOC_CTX *mem_ctx,
2622 int argc, const char **argv)
2624 WERROR result;
2625 NTSTATUS status;
2626 const char *printername;
2627 struct policy_handle pol = { 0, };
2628 union spoolss_PrinterInfo info;
2629 enum winreg_Type type;
2630 union spoolss_PrinterData data;
2631 DATA_BLOB blob;
2632 struct dcerpc_binding_handle *b = cli->binding_handle;
2633 int error = 0;
2635 /* parse the command arguments */
2636 if (argc < 5) {
2637 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2638 " <value> <data>\n",
2639 argv[0]);
2640 return WERR_OK;
2643 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2645 type = REG_NONE;
2647 if (strequal(argv[2], "string")) {
2648 type = REG_SZ;
2651 if (strequal(argv[2], "binary")) {
2652 type = REG_BINARY;
2655 if (strequal(argv[2], "dword")) {
2656 type = REG_DWORD;
2659 if (strequal(argv[2], "multistring")) {
2660 type = REG_MULTI_SZ;
2663 if (type == REG_NONE) {
2664 printf("Unknown data type: %s\n", argv[2]);
2665 result = WERR_INVALID_PARAMETER;
2666 goto done;
2669 /* get a printer handle */
2671 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2672 printername,
2673 SEC_FLAG_MAXIMUM_ALLOWED,
2674 &pol);
2675 if (!W_ERROR_IS_OK(result)) {
2676 goto done;
2679 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2680 &pol,
2683 &info);
2684 if (!W_ERROR_IS_OK(result)) {
2685 goto done;
2688 printf("%s\n", current_timestring(mem_ctx, true));
2689 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2691 /* Set the printer data */
2693 switch (type) {
2694 case REG_SZ:
2695 data.string = talloc_strdup(mem_ctx, argv[4]);
2696 W_ERROR_HAVE_NO_MEMORY(data.string);
2697 break;
2698 case REG_DWORD:
2699 data.value = smb_strtoul(argv[4],
2700 NULL,
2702 &error,
2703 SMB_STR_STANDARD);
2704 if (error != 0) {
2705 result = WERR_INVALID_PARAMETER;
2706 goto done;
2709 break;
2710 case REG_BINARY:
2711 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2712 break;
2713 case REG_MULTI_SZ: {
2714 int i;
2715 size_t num_strings;
2716 const char **strings = NULL;
2718 num_strings = 0;
2720 for (i=4; i<argc; i++) {
2721 if (strcmp(argv[i], "NULL") == 0) {
2722 argv[i] = "";
2724 if (!add_string_to_array(mem_ctx, argv[i],
2725 &strings,
2726 &num_strings)) {
2727 result = WERR_NOT_ENOUGH_MEMORY;
2728 goto done;
2731 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2732 if (!data.string_array) {
2733 result = WERR_NOT_ENOUGH_MEMORY;
2734 goto done;
2736 for (i=0; i < num_strings; i++) {
2737 data.string_array[i] = strings[i];
2739 break;
2741 default:
2742 printf("Unknown data type: %s\n", argv[2]);
2743 result = WERR_INVALID_PARAMETER;
2744 goto done;
2747 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2748 if (!W_ERROR_IS_OK(result)) {
2749 goto done;
2752 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2753 &pol,
2754 argv[3], /* value_name */
2755 type,
2756 blob.data,
2757 blob.length,
2758 &result);
2759 if (!NT_STATUS_IS_OK(status)) {
2760 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2761 result = ntstatus_to_werror(status);
2762 goto done;
2764 if (!W_ERROR_IS_OK(result)) {
2765 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2766 goto done;
2768 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2770 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2771 &pol,
2774 &info);
2775 if (!W_ERROR_IS_OK(result)) {
2776 goto done;
2779 printf("%s\n", current_timestring(mem_ctx, true));
2780 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2782 done:
2783 /* cleanup */
2784 if (is_valid_policy_hnd(&pol)) {
2785 WERROR _result;
2786 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2789 return result;
2792 /****************************************************************************
2793 ****************************************************************************/
2795 static void display_job_info1(struct spoolss_JobInfo1 *r)
2797 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2798 r->user_name, r->document_name, r->text_status, r->pages_printed,
2799 r->total_pages);
2802 /****************************************************************************
2803 ****************************************************************************/
2805 static void display_job_info2(struct spoolss_JobInfo2 *r)
2807 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2808 r->position, r->job_id,
2809 r->user_name, r->document_name, r->text_status, r->pages_printed,
2810 r->total_pages, r->size);
2813 /****************************************************************************
2814 ****************************************************************************/
2816 static void display_job_info3(struct spoolss_JobInfo3 *r)
2818 printf("jobid[%d], next_jobid[%d]\n",
2819 r->job_id, r->next_job_id);
2822 /****************************************************************************
2823 ****************************************************************************/
2825 static void display_job_info4(struct spoolss_JobInfo4 *r)
2827 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2828 r->position, r->job_id,
2829 r->user_name, r->document_name, r->text_status, r->pages_printed,
2830 r->total_pages, r->size, r->size_high);
2833 /****************************************************************************
2834 ****************************************************************************/
2836 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2837 TALLOC_CTX *mem_ctx, int argc,
2838 const char **argv)
2840 WERROR result;
2841 uint32_t level = 1, count, i;
2842 const char *printername;
2843 struct policy_handle hnd;
2844 union spoolss_JobInfo *info;
2845 struct dcerpc_binding_handle *b = cli->binding_handle;
2847 if (argc < 2 || argc > 3) {
2848 printf("Usage: %s printername [level]\n", argv[0]);
2849 return WERR_OK;
2852 if (argc == 3) {
2853 level = atoi(argv[2]);
2856 /* Open printer handle */
2858 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2860 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2861 printername,
2862 SEC_FLAG_MAXIMUM_ALLOWED,
2863 &hnd);
2864 if (!W_ERROR_IS_OK(result))
2865 goto done;
2867 /* Enumerate ports */
2869 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2870 &hnd,
2871 0, /* firstjob */
2872 1000, /* numjobs */
2873 level,
2875 &count,
2876 &info);
2877 if (!W_ERROR_IS_OK(result)) {
2878 goto done;
2881 for (i = 0; i < count; i++) {
2882 switch (level) {
2883 case 1:
2884 display_job_info1(&info[i].info1);
2885 break;
2886 case 2:
2887 display_job_info2(&info[i].info2);
2888 break;
2889 default:
2890 d_printf("unknown info level %d\n", level);
2891 break;
2895 done:
2896 if (is_valid_policy_hnd(&hnd)) {
2897 WERROR _result;
2898 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2901 return result;
2904 /****************************************************************************
2905 ****************************************************************************/
2907 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2908 TALLOC_CTX *mem_ctx, int argc,
2909 const char **argv)
2911 WERROR result;
2912 const char *printername;
2913 struct policy_handle hnd;
2914 uint32_t job_id;
2915 uint32_t level = 1;
2916 union spoolss_JobInfo info;
2917 struct dcerpc_binding_handle *b = cli->binding_handle;
2919 if (argc < 3 || argc > 4) {
2920 printf("Usage: %s printername job_id [level]\n", argv[0]);
2921 return WERR_OK;
2924 job_id = atoi(argv[2]);
2926 if (argc == 4) {
2927 level = atoi(argv[3]);
2930 /* Open printer handle */
2932 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2934 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2935 printername,
2936 SEC_FLAG_MAXIMUM_ALLOWED,
2937 &hnd);
2938 if (!W_ERROR_IS_OK(result)) {
2939 goto done;
2942 /* Enumerate ports */
2944 result = rpccli_spoolss_getjob(cli, mem_ctx,
2945 &hnd,
2946 job_id,
2947 level,
2949 &info);
2951 if (!W_ERROR_IS_OK(result)) {
2952 goto done;
2955 switch (level) {
2956 case 1:
2957 display_job_info1(&info.info1);
2958 break;
2959 case 2:
2960 display_job_info2(&info.info2);
2961 break;
2962 case 3:
2963 display_job_info3(&info.info3);
2964 break;
2965 case 4:
2966 display_job_info4(&info.info4);
2967 break;
2968 default:
2969 d_printf("unknown info level %d\n", level);
2970 break;
2973 done:
2974 if (is_valid_policy_hnd(&hnd)) {
2975 WERROR _result;
2976 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2979 return result;
2982 /****************************************************************************
2983 ****************************************************************************/
2985 static struct {
2986 const char *name;
2987 enum spoolss_JobControl val;
2988 } cmdvals[] = {
2989 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2990 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2991 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2992 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2993 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2994 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2995 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2996 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2997 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
3000 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
3002 int i;
3004 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
3005 if (strequal(cmdvals[i].name, cmd)) {
3006 return cmdvals[i].val;
3009 return (enum spoolss_JobControl)atoi(cmd);
3012 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
3013 TALLOC_CTX *mem_ctx, int argc,
3014 const char **argv)
3016 WERROR result;
3017 NTSTATUS status;
3018 const char *printername;
3019 struct policy_handle hnd;
3020 uint32_t job_id;
3021 enum spoolss_JobControl command;
3022 struct dcerpc_binding_handle *b = cli->binding_handle;
3024 if (argc != 4) {
3025 printf("Usage: %s printername job_id command\n", argv[0]);
3026 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3027 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3028 return WERR_OK;
3031 job_id = atoi(argv[2]);
3032 command = parse_setjob_command(argv[3]);
3034 /* Open printer handle */
3036 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3038 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3039 printername,
3040 SEC_FLAG_MAXIMUM_ALLOWED,
3041 &hnd);
3042 if (!W_ERROR_IS_OK(result)) {
3043 goto done;
3046 /* Set Job */
3048 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3049 &hnd,
3050 job_id,
3051 NULL,
3052 command,
3053 &result);
3054 if (!NT_STATUS_IS_OK(status)) {
3055 result = ntstatus_to_werror(status);
3056 goto done;
3058 if (!W_ERROR_IS_OK(result)) {
3059 goto done;
3062 done:
3063 if (is_valid_policy_hnd(&hnd)) {
3064 WERROR _result;
3065 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3068 return result;
3071 /****************************************************************************
3072 ****************************************************************************/
3074 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
3075 TALLOC_CTX *mem_ctx, int argc,
3076 const char **argv)
3078 WERROR result;
3079 NTSTATUS status;
3080 const char *printername;
3081 struct policy_handle hnd;
3082 uint32_t value_needed;
3083 enum winreg_Type type;
3084 uint32_t data_needed;
3085 struct dcerpc_binding_handle *b = cli->binding_handle;
3086 struct spoolss_EnumPrinterData r;
3088 if (argc != 2) {
3089 printf("Usage: %s printername\n", argv[0]);
3090 return WERR_OK;
3093 /* Open printer handle */
3095 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3097 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3098 printername,
3099 SEC_FLAG_MAXIMUM_ALLOWED,
3100 &hnd);
3101 if (!W_ERROR_IS_OK(result)) {
3102 goto done;
3105 /* Enumerate data */
3107 r.in.handle = &hnd;
3108 r.in.enum_index = 0;
3109 r.in.value_offered = 0;
3110 r.in.data_offered = 0;
3111 r.out.value_name = NULL;
3112 r.out.value_needed = &value_needed;
3113 r.out.type = &type;
3114 r.out.data = NULL;
3115 r.out.data_needed = &data_needed;
3117 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3118 if (!NT_STATUS_IS_OK(status)) {
3119 result = ntstatus_to_werror(status);
3120 goto done;
3123 if (!W_ERROR_IS_OK(r.out.result)) {
3124 result = r.out.result;
3125 goto done;
3128 r.in.data_offered = *r.out.data_needed;
3129 r.in.value_offered = *r.out.value_needed;
3130 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3131 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3133 do {
3135 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3136 if (!NT_STATUS_IS_OK(status)) {
3137 result = ntstatus_to_werror(status);
3138 goto done;
3141 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3142 result = WERR_OK;
3143 break;
3146 r.in.enum_index++;
3148 display_reg_value(r.out.value_name, *r.out.type,
3149 data_blob_const(r.out.data, r.in.data_offered));
3151 } while (W_ERROR_IS_OK(r.out.result));
3153 done:
3154 if (is_valid_policy_hnd(&hnd)) {
3155 WERROR _result;
3156 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3159 return result;
3162 /****************************************************************************
3163 ****************************************************************************/
3165 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3166 TALLOC_CTX *mem_ctx, int argc,
3167 const char **argv)
3169 WERROR result;
3170 uint32_t i;
3171 const char *printername;
3172 struct policy_handle hnd;
3173 uint32_t count;
3174 struct spoolss_PrinterEnumValues *info;
3175 struct dcerpc_binding_handle *b = cli->binding_handle;
3177 if (argc != 3) {
3178 printf("Usage: %s printername <keyname>\n", argv[0]);
3179 return WERR_OK;
3182 /* Open printer handle */
3184 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3186 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3187 printername,
3188 SEC_FLAG_MAXIMUM_ALLOWED,
3189 &hnd);
3190 if (!W_ERROR_IS_OK(result)) {
3191 goto done;
3194 /* Enumerate subkeys */
3196 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3197 &hnd,
3198 argv[2],
3200 &count,
3201 &info);
3202 if (!W_ERROR_IS_OK(result)) {
3203 goto done;
3206 for (i=0; i < count; i++) {
3207 display_printer_data(info[i].value_name,
3208 info[i].type,
3209 info[i].data->data,
3210 info[i].data->length);
3213 done:
3214 if (is_valid_policy_hnd(&hnd)) {
3215 WERROR _result;
3216 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3219 return result;
3222 /****************************************************************************
3223 ****************************************************************************/
3225 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3226 TALLOC_CTX *mem_ctx, int argc,
3227 const char **argv)
3229 WERROR result;
3230 const char *printername;
3231 const char *keyname = NULL;
3232 struct policy_handle hnd;
3233 const char **key_buffer = NULL;
3234 int i;
3235 uint32_t offered = 0;
3236 struct dcerpc_binding_handle *b = cli->binding_handle;
3238 if (argc < 2 || argc > 4) {
3239 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3240 return WERR_OK;
3243 if (argc >= 3) {
3244 keyname = argv[2];
3245 } else {
3246 keyname = "";
3249 if (argc == 4) {
3250 offered = atoi(argv[3]);
3253 /* Open printer handle */
3255 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3257 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3258 printername,
3259 SEC_FLAG_MAXIMUM_ALLOWED,
3260 &hnd);
3261 if (!W_ERROR_IS_OK(result)) {
3262 goto done;
3265 /* Enumerate subkeys */
3267 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3268 &hnd,
3269 keyname,
3270 &key_buffer,
3271 offered);
3273 if (!W_ERROR_IS_OK(result)) {
3274 goto done;
3277 for (i=0; key_buffer && key_buffer[i]; i++) {
3278 printf("%s\n", key_buffer[i]);
3281 done:
3283 if (is_valid_policy_hnd(&hnd)) {
3284 WERROR _result;
3285 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3288 return result;
3291 /****************************************************************************
3292 ****************************************************************************/
3294 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3295 TALLOC_CTX *mem_ctx, int argc,
3296 const char **argv)
3298 const char *printername;
3299 const char *clientname;
3300 struct policy_handle hnd = { 0, };
3301 WERROR result;
3302 NTSTATUS status;
3303 struct spoolss_NotifyOption option;
3304 struct dcerpc_binding_handle *b = cli->binding_handle;
3306 if (argc != 2) {
3307 printf("Usage: %s printername\n", argv[0]);
3308 result = WERR_OK;
3309 goto done;
3312 /* Open printer */
3314 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3316 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3317 printername,
3318 SEC_FLAG_MAXIMUM_ALLOWED,
3319 &hnd);
3320 if (!W_ERROR_IS_OK(result)) {
3321 printf("Error opening %s\n", argv[1]);
3322 goto done;
3325 /* Create spool options */
3327 option.version = 2;
3328 option.count = 2;
3330 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3331 if (option.types == NULL) {
3332 result = WERR_NOT_ENOUGH_MEMORY;
3333 goto done;
3336 option.types[0].type = PRINTER_NOTIFY_TYPE;
3337 option.types[0].count = 1;
3338 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3339 if (option.types[0].fields == NULL) {
3340 result = WERR_NOT_ENOUGH_MEMORY;
3341 goto done;
3343 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3345 option.types[1].type = JOB_NOTIFY_TYPE;
3346 option.types[1].count = 1;
3347 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3348 if (option.types[1].fields == NULL) {
3349 result = WERR_NOT_ENOUGH_MEMORY;
3350 goto done;
3352 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3354 clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3355 if (!clientname) {
3356 result = WERR_NOT_ENOUGH_MEMORY;
3357 goto done;
3360 /* Send rffpcnex */
3362 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3363 &hnd,
3366 clientname,
3367 123,
3368 &option,
3369 &result);
3370 if (!NT_STATUS_IS_OK(status)) {
3371 result = ntstatus_to_werror(status);
3372 goto done;
3374 if (!W_ERROR_IS_OK(result)) {
3375 printf("Error rffpcnex %s\n", argv[1]);
3376 goto done;
3379 done:
3380 if (is_valid_policy_hnd(&hnd)) {
3381 WERROR _result;
3382 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3385 return result;
3388 /****************************************************************************
3389 ****************************************************************************/
3391 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3392 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3394 union spoolss_PrinterInfo info1, info2;
3395 WERROR werror;
3396 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3398 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3399 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3400 hnd1,
3403 &info1);
3404 if ( !W_ERROR_IS_OK(werror) ) {
3405 printf("failed (%s)\n", win_errstr(werror));
3406 talloc_destroy(mem_ctx);
3407 return false;
3409 printf("ok\n");
3411 printf("Retrieving printer properties for %s...", cli2->desthost);
3412 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3413 hnd2,
3416 &info2);
3417 if ( !W_ERROR_IS_OK(werror) ) {
3418 printf("failed (%s)\n", win_errstr(werror));
3419 talloc_destroy(mem_ctx);
3420 return false;
3422 printf("ok\n");
3424 talloc_destroy(mem_ctx);
3426 return true;
3429 /****************************************************************************
3430 ****************************************************************************/
3432 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3433 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3435 union spoolss_PrinterInfo info1, info2;
3436 WERROR werror;
3437 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3438 struct security_descriptor *sd1, *sd2;
3439 bool result = true;
3442 printf("Retrieving printer security for %s...", cli1->desthost);
3443 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3444 hnd1,
3447 &info1);
3448 if ( !W_ERROR_IS_OK(werror) ) {
3449 printf("failed (%s)\n", win_errstr(werror));
3450 result = false;
3451 goto done;
3453 printf("ok\n");
3455 printf("Retrieving printer security for %s...", cli2->desthost);
3456 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3457 hnd2,
3460 &info2);
3461 if ( !W_ERROR_IS_OK(werror) ) {
3462 printf("failed (%s)\n", win_errstr(werror));
3463 result = false;
3464 goto done;
3466 printf("ok\n");
3469 printf("++ ");
3471 sd1 = info1.info3.secdesc;
3472 sd2 = info2.info3.secdesc;
3474 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3475 printf("NULL secdesc!\n");
3476 result = false;
3477 goto done;
3480 if (!security_descriptor_equal( sd1, sd2 ) ) {
3481 printf("Security Descriptors *not* equal!\n");
3482 result = false;
3483 goto done;
3486 printf("Security descriptors match\n");
3488 done:
3489 talloc_destroy(mem_ctx);
3490 return result;
3494 /****************************************************************************
3495 ****************************************************************************/
3497 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3498 TALLOC_CTX *mem_ctx, int argc,
3499 const char **argv)
3501 const char *printername;
3502 char *printername_path = NULL;
3503 struct cli_state *cli_server2 = NULL;
3504 struct rpc_pipe_client *cli2 = NULL;
3505 struct policy_handle hPrinter1, hPrinter2;
3506 NTSTATUS nt_status;
3507 WERROR werror;
3508 struct cli_credentials *creds = samba_cmdline_get_creds();
3510 if ( argc != 3 ) {
3511 printf("Usage: %s <printer> <server>\n", argv[0]);
3512 return WERR_OK;
3515 printername = argv[1];
3517 /* first get the connection to the remote server */
3519 nt_status = cli_full_connection_creds(&cli_server2, lp_netbios_name(), argv[2],
3520 NULL, 0,
3521 "IPC$", "IPC",
3522 creds,
3523 CLI_FULL_CONNECTION_IPC);
3524 if ( !NT_STATUS_IS_OK(nt_status) )
3525 return WERR_GEN_FAILURE;
3527 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3528 &cli2);
3529 if (!NT_STATUS_IS_OK(nt_status)) {
3530 printf("failed to open spoolss pipe on server %s (%s)\n",
3531 argv[2], nt_errstr(nt_status));
3532 return WERR_GEN_FAILURE;
3535 /* now open up both printers */
3537 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3539 printf("Opening %s...", printername_path);
3541 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3542 printername_path,
3543 PRINTER_ALL_ACCESS,
3544 &hPrinter1);
3545 if ( !W_ERROR_IS_OK(werror) ) {
3546 printf("failed (%s)\n", win_errstr(werror));
3547 goto done;
3549 printf("ok\n");
3551 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3553 printf("Opening %s...", printername_path);
3554 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3555 printername_path,
3556 PRINTER_ALL_ACCESS,
3557 &hPrinter2);
3558 if ( !W_ERROR_IS_OK(werror) ) {
3559 printf("failed (%s)\n", win_errstr(werror));
3560 goto done;
3562 printf("ok\n");
3564 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3565 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3566 #if 0
3567 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3568 #endif
3571 done:
3572 /* cleanup */
3574 printf("Closing printers...");
3576 WERROR _result;
3577 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3578 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3580 printf("ok\n");
3582 /* close the second remote connection */
3584 cli_shutdown( cli_server2 );
3585 return WERR_OK;
3588 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3590 printf("print_processor_name: %s\n", r->print_processor_name);
3593 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3594 TALLOC_CTX *mem_ctx, int argc,
3595 const char **argv)
3597 WERROR werror;
3598 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3599 uint32_t num_procs, level = 1, i;
3600 union spoolss_PrintProcessorInfo *procs;
3602 /* Parse the command arguments */
3604 if (argc < 1 || argc > 4) {
3605 printf ("Usage: %s [environment] [level]\n", argv[0]);
3606 return WERR_OK;
3609 if (argc >= 2) {
3610 environment = argv[1];
3613 if (argc == 3) {
3614 level = atoi(argv[2]);
3617 /* Enumerate Print Processors */
3619 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3620 cli->srv_name_slash,
3621 environment,
3622 level,
3624 &num_procs,
3625 &procs);
3626 if (!W_ERROR_IS_OK(werror))
3627 goto done;
3629 /* Display output */
3631 for (i = 0; i < num_procs; i++) {
3632 switch (level) {
3633 case 1:
3634 display_proc_info1(&procs[i].info1);
3635 break;
3639 done:
3640 return werror;
3643 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3645 printf("name_array: %s\n", r->name_array);
3648 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3649 TALLOC_CTX *mem_ctx, int argc,
3650 const char **argv)
3652 WERROR werror;
3653 const char *print_processor_name = "winprint";
3654 uint32_t num_procs, level = 1, i;
3655 union spoolss_PrintProcDataTypesInfo *procs;
3657 /* Parse the command arguments */
3659 if (argc < 1 || argc > 4) {
3660 printf ("Usage: %s [environment] [level]\n", argv[0]);
3661 return WERR_OK;
3664 if (argc >= 2) {
3665 print_processor_name = argv[1];
3668 if (argc == 3) {
3669 level = atoi(argv[2]);
3672 /* Enumerate Print Processor Data Types */
3674 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3675 cli->srv_name_slash,
3676 print_processor_name,
3677 level,
3679 &num_procs,
3680 &procs);
3681 if (!W_ERROR_IS_OK(werror))
3682 goto done;
3684 /* Display output */
3686 for (i = 0; i < num_procs; i++) {
3687 switch (level) {
3688 case 1:
3689 display_proc_data_types_info1(&procs[i].info1);
3690 break;
3694 done:
3695 return werror;
3698 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3700 printf("monitor_name: %s\n", r->monitor_name);
3703 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3705 printf("monitor_name: %s\n", r->monitor_name);
3706 printf("environment: %s\n", r->environment);
3707 printf("dll_name: %s\n", r->dll_name);
3710 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3711 TALLOC_CTX *mem_ctx, int argc,
3712 const char **argv)
3714 WERROR werror;
3715 uint32_t count, level = 1, i;
3716 union spoolss_MonitorInfo *info;
3718 /* Parse the command arguments */
3720 if (argc > 2) {
3721 printf("Usage: %s [level]\n", argv[0]);
3722 return WERR_OK;
3725 if (argc == 2) {
3726 level = atoi(argv[1]);
3729 /* Enumerate Print Monitors */
3731 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3732 cli->srv_name_slash,
3733 level,
3735 &count,
3736 &info);
3737 if (!W_ERROR_IS_OK(werror)) {
3738 goto done;
3741 /* Display output */
3743 for (i = 0; i < count; i++) {
3744 switch (level) {
3745 case 1:
3746 display_monitor1(&info[i].info1);
3747 break;
3748 case 2:
3749 display_monitor2(&info[i].info2);
3750 break;
3754 done:
3755 return werror;
3758 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3759 TALLOC_CTX *mem_ctx, int argc,
3760 const char **argv)
3762 WERROR result;
3763 NTSTATUS status;
3764 struct policy_handle handle, gdi_handle;
3765 const char *printername;
3766 struct spoolss_DevmodeContainer devmode_ctr;
3767 struct dcerpc_binding_handle *b = cli->binding_handle;
3769 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3771 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3772 printername,
3773 SEC_FLAG_MAXIMUM_ALLOWED,
3774 &handle);
3775 if (!W_ERROR_IS_OK(result)) {
3776 return result;
3779 ZERO_STRUCT(devmode_ctr);
3781 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3782 &handle,
3783 &gdi_handle,
3784 &devmode_ctr,
3785 &result);
3786 if (!NT_STATUS_IS_OK(status)) {
3787 result = ntstatus_to_werror(status);
3788 goto done;
3790 if (!W_ERROR_IS_OK(result)) {
3791 goto done;
3794 done:
3795 if (is_valid_policy_hnd(&gdi_handle)) {
3796 WERROR _result;
3797 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3799 if (is_valid_policy_hnd(&handle)) {
3800 WERROR _result;
3801 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3804 return result;
3807 static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3808 TALLOC_CTX *mem_ctx, int argc,
3809 const char **argv)
3811 WERROR result;
3812 NTSTATUS status;
3813 struct policy_handle handle, gdi_handle;
3814 const char *printername;
3815 struct spoolss_DevmodeContainer devmode_ctr;
3816 struct dcerpc_binding_handle *b = cli->binding_handle;
3817 DATA_BLOB in,out;
3818 uint32_t count = 0;
3820 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3822 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3823 printername,
3824 SEC_FLAG_MAXIMUM_ALLOWED,
3825 &handle);
3826 if (!W_ERROR_IS_OK(result)) {
3827 return result;
3830 ZERO_STRUCT(devmode_ctr);
3832 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3833 &handle,
3834 &gdi_handle,
3835 &devmode_ctr,
3836 &result);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 result = ntstatus_to_werror(status);
3839 goto done;
3841 if (!W_ERROR_IS_OK(result)) {
3842 goto done;
3845 in = data_blob_string_const("");
3846 out = data_blob_talloc_zero(mem_ctx, 4);
3848 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3849 &gdi_handle,
3850 in.data,
3851 in.length,
3852 out.data,
3853 out.length,
3854 0, /* ul */
3855 &result);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 result = ntstatus_to_werror(status);
3858 goto done;
3860 if (!W_ERROR_IS_OK(result)) {
3861 goto done;
3864 count = IVAL(out.data, 0);
3866 out = data_blob_talloc_zero(mem_ctx,
3867 count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3869 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3870 &gdi_handle,
3871 in.data,
3872 in.length,
3873 out.data,
3874 out.length,
3875 0, /* ul */
3876 &result);
3877 if (!NT_STATUS_IS_OK(status)) {
3878 result = ntstatus_to_werror(status);
3879 goto done;
3881 if (!W_ERROR_IS_OK(result)) {
3882 goto done;
3886 enum ndr_err_code ndr_err;
3887 struct UNIVERSAL_FONT_ID_ctr r;
3889 ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3890 (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3891 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3892 NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3896 done:
3897 if (is_valid_policy_hnd(&gdi_handle)) {
3898 WERROR _result;
3899 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3901 if (is_valid_policy_hnd(&handle)) {
3902 WERROR _result;
3903 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3906 return result;
3909 static WERROR cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client *cli,
3910 TALLOC_CTX *mem_ctx, int argc,
3911 const char **argv)
3913 NTSTATUS status;
3914 HRESULT result;
3915 struct dcerpc_binding_handle *b = cli->binding_handle;
3916 const char *architecture = SPOOLSS_ARCHITECTURE_x64;
3917 struct spoolss_CorePrinterDriver core_printer_drivers;
3918 DATA_BLOB blob;
3919 bool ok;
3920 int i;
3921 uint32_t count;
3922 const char **array;
3924 if (argc == 1) {
3925 count = 1;
3926 array = talloc_zero_array(mem_ctx, const char *, count + 1);
3927 if (array == NULL) {
3928 return WERR_NOT_ENOUGH_MEMORY;
3930 array[0] = talloc_strdup(array, SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
3931 if (array[0] == NULL) {
3932 return WERR_NOT_ENOUGH_MEMORY;
3934 } else {
3935 count = argc -1;
3936 array = talloc_zero_array(mem_ctx, const char *, count + 1);
3937 if (array == NULL) {
3938 return WERR_NOT_ENOUGH_MEMORY;
3940 for (i = 0; i < argc - 1; i++) {
3941 array[i] = talloc_strdup(array, argv[i + 1]);
3942 if (array[i] == NULL) {
3943 return WERR_NOT_ENOUGH_MEMORY;
3948 ok = push_reg_multi_sz(mem_ctx, &blob, array);
3949 if (!ok) {
3950 return WERR_NOT_ENOUGH_MEMORY;
3953 status = dcerpc_spoolss_GetCorePrinterDrivers(b, mem_ctx,
3954 cli->srv_name_slash,
3955 architecture,
3956 blob.length/2,
3957 (uint16_t *)blob.data,
3958 count,
3959 &core_printer_drivers,
3960 &result);
3961 if (!NT_STATUS_IS_OK(status)) {
3962 return ntstatus_to_werror(status);
3965 if (!HRES_IS_OK(result)) {
3966 return W_ERROR(WIN32_FROM_HRESULT(result));
3969 return WERR_OK;
3972 static WERROR cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client *cli,
3973 TALLOC_CTX *mem_ctx, int argc,
3974 const char **argv)
3976 NTSTATUS status;
3977 WERROR result;
3978 struct dcerpc_binding_handle *b = cli->binding_handle;
3979 const char *servername = cli->srv_name_slash;
3980 DATA_BLOB in = data_blob_null;
3981 struct spoolss_PrinterInfo4 *info;
3982 uint32_t needed, count;
3984 if (argc > 2) {
3985 printf("usage: %s [servername]\n", argv[0]);
3986 return WERR_OK;
3989 if (argc > 1) {
3990 servername = argv[1];
3993 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
3994 servername,
3995 &in,
3996 in.length,
3997 &count,
3998 &info,
3999 &needed,
4000 &result);
4001 if (!NT_STATUS_IS_OK(status)) {
4002 return ntstatus_to_werror(status);
4005 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
4006 in = data_blob_talloc_zero(mem_ctx, needed);
4007 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4008 servername,
4009 &in,
4010 in.length,
4011 &count,
4012 &info,
4013 &needed,
4014 &result);
4015 if (!NT_STATUS_IS_OK(status)) {
4016 return ntstatus_to_werror(status);
4020 return result;
4023 static WERROR cmd_spoolss_add_permachineconnection(struct rpc_pipe_client *cli,
4024 TALLOC_CTX *mem_ctx, int argc,
4025 const char **argv)
4027 NTSTATUS status;
4028 WERROR result;
4029 struct dcerpc_binding_handle *b = cli->binding_handle;
4030 const char *servername = cli->srv_name_slash;
4031 const char *printername = "Microsoft Print to PDF";
4032 const char *printserver = "samba.org";
4033 const char *provider = ""; /* refers to Win32spl.dll then */
4034 const char *composed_printername;
4036 if (argc > 5) {
4037 printf("usage: %s [servername] [printername] [printserver] [provider]\n", argv[0]);
4038 return WERR_OK;
4041 if (argc > 1) {
4042 servername = argv[1];
4044 if (argc > 2) {
4045 printername = argv[2];
4047 if (argc > 3) {
4048 printserver = argv[3];
4050 if (argc > 4) {
4051 provider = argv[4];
4054 composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4055 printername);
4056 if (composed_printername == NULL) {
4057 return WERR_NOT_ENOUGH_MEMORY;
4059 status = dcerpc_spoolss_AddPerMachineConnection(b, mem_ctx,
4060 servername,
4061 composed_printername,
4062 printserver,
4063 provider,
4064 &result);
4065 if (!NT_STATUS_IS_OK(status)) {
4066 return ntstatus_to_werror(status);
4069 return result;
4072 static WERROR cmd_spoolss_del_permachineconnection(struct rpc_pipe_client *cli,
4073 TALLOC_CTX *mem_ctx, int argc,
4074 const char **argv)
4076 NTSTATUS status;
4077 WERROR result;
4078 struct dcerpc_binding_handle *b = cli->binding_handle;
4079 const char *servername = cli->srv_name_slash;
4080 const char *printername = "Microsoft Print to PDF";
4081 const char *composed_printername;
4083 if (argc > 3) {
4084 printf("usage: %s [servername] [printername]\n", argv[0]);
4085 return WERR_OK;
4088 if (argc > 1) {
4089 servername = argv[1];
4091 if (argc > 2) {
4092 printername = argv[2];
4095 composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4096 printername);
4097 if (composed_printername == NULL) {
4098 return WERR_NOT_ENOUGH_MEMORY;
4101 status = dcerpc_spoolss_DeletePerMachineConnection(b, mem_ctx,
4102 servername,
4103 composed_printername,
4104 &result);
4105 if (!NT_STATUS_IS_OK(status)) {
4106 return ntstatus_to_werror(status);
4109 return result;
4112 /* List of commands exported by this module */
4113 struct cmd_set spoolss_commands[] = {
4116 .name = "SPOOLSS",
4120 .name = "adddriver",
4121 .returntype = RPC_RTYPE_WERROR,
4122 .ntfn = NULL,
4123 .wfn = cmd_spoolss_addprinterdriver,
4124 .table = &ndr_table_spoolss,
4125 .rpc_pipe = NULL,
4126 .description = "Add a print driver",
4127 .usage = "",
4128 .use_netlogon_creds = false,
4131 .name = "addprinter",
4132 .returntype = RPC_RTYPE_WERROR,
4133 .ntfn = NULL,
4134 .wfn = cmd_spoolss_addprinterex,
4135 .table = &ndr_table_spoolss,
4136 .rpc_pipe = NULL,
4137 .description = "Add a printer",
4138 .usage = "",
4141 .name = "deldriver",
4142 .returntype = RPC_RTYPE_WERROR,
4143 .ntfn = NULL,
4144 .wfn = cmd_spoolss_deletedriver,
4145 .table = &ndr_table_spoolss,
4146 .rpc_pipe = NULL,
4147 .description = "Delete a printer driver",
4148 .usage = "",
4151 .name = "deldriverex",
4152 .returntype = RPC_RTYPE_WERROR,
4153 .ntfn = NULL,
4154 .wfn = cmd_spoolss_deletedriverex,
4155 .table = &ndr_table_spoolss,
4156 .rpc_pipe = NULL,
4157 .description = "Delete a printer driver with files",
4158 .usage = "",
4161 .name = "enumdata",
4162 .returntype = RPC_RTYPE_WERROR,
4163 .ntfn = NULL,
4164 .wfn = cmd_spoolss_enum_data,
4165 .table = &ndr_table_spoolss,
4166 .rpc_pipe = NULL,
4167 .description = "Enumerate printer data",
4168 .usage = "",
4171 .name = "enumdataex",
4172 .returntype = RPC_RTYPE_WERROR,
4173 .ntfn = NULL,
4174 .wfn = cmd_spoolss_enum_data_ex,
4175 .table = &ndr_table_spoolss,
4176 .rpc_pipe = NULL,
4177 .description = "Enumerate printer data for a key",
4178 .usage = "",
4181 .name = "enumkey",
4182 .returntype = RPC_RTYPE_WERROR,
4183 .ntfn = NULL,
4184 .wfn = cmd_spoolss_enum_printerkey,
4185 .table = &ndr_table_spoolss,
4186 .rpc_pipe = NULL,
4187 .description = "Enumerate printer keys",
4188 .usage = "",
4191 .name = "enumjobs",
4192 .returntype = RPC_RTYPE_WERROR,
4193 .ntfn = NULL,
4194 .wfn = cmd_spoolss_enum_jobs,
4195 .table = &ndr_table_spoolss,
4196 .rpc_pipe = NULL,
4197 .description = "Enumerate print jobs",
4198 .usage = "",
4201 .name = "getjob",
4202 .returntype = RPC_RTYPE_WERROR,
4203 .ntfn = NULL,
4204 .wfn = cmd_spoolss_get_job,
4205 .table = &ndr_table_spoolss,
4206 .rpc_pipe = NULL,
4207 .description = "Get print job",
4208 .usage = "",
4211 .name = "setjob",
4212 .returntype = RPC_RTYPE_WERROR,
4213 .ntfn = NULL,
4214 .wfn = cmd_spoolss_set_job,
4215 .table = &ndr_table_spoolss,
4216 .rpc_pipe = NULL,
4217 .description = "Set print job",
4218 .usage = "",
4221 .name = "enumports",
4222 .returntype = RPC_RTYPE_WERROR,
4223 .ntfn = NULL,
4224 .wfn = cmd_spoolss_enum_ports,
4225 .table = &ndr_table_spoolss,
4226 .rpc_pipe = NULL,
4227 .description = "Enumerate printer ports",
4228 .usage = "",
4231 .name = "enumdrivers",
4232 .returntype = RPC_RTYPE_WERROR,
4233 .ntfn = NULL,
4234 .wfn = cmd_spoolss_enum_drivers,
4235 .table = &ndr_table_spoolss,
4236 .rpc_pipe = NULL,
4237 .description = "Enumerate installed printer drivers",
4238 .usage = "",
4241 .name = "enumprinters",
4242 .returntype = RPC_RTYPE_WERROR,
4243 .ntfn = NULL,
4244 .wfn = cmd_spoolss_enum_printers,
4245 .table = &ndr_table_spoolss,
4246 .rpc_pipe = NULL,
4247 .description = "Enumerate printers",
4248 .usage = "",
4251 .name = "getdata",
4252 .returntype = RPC_RTYPE_WERROR,
4253 .ntfn = NULL,
4254 .wfn = cmd_spoolss_getprinterdata,
4255 .table = &ndr_table_spoolss,
4256 .rpc_pipe = NULL,
4257 .description = "Get print driver data",
4258 .usage = "",
4261 .name = "getdataex",
4262 .returntype = RPC_RTYPE_WERROR,
4263 .ntfn = NULL,
4264 .wfn = cmd_spoolss_getprinterdataex,
4265 .table = &ndr_table_spoolss,
4266 .rpc_pipe = NULL,
4267 .description = "Get printer driver data with keyname",
4268 .usage = "",
4271 .name = "getdriver",
4272 .returntype = RPC_RTYPE_WERROR,
4273 .ntfn = NULL,
4274 .wfn = cmd_spoolss_getdriver,
4275 .table = &ndr_table_spoolss,
4276 .rpc_pipe = NULL,
4277 .description = "Get print driver information",
4278 .usage = "",
4281 .name = "getdriverdir",
4282 .returntype = RPC_RTYPE_WERROR,
4283 .ntfn = NULL,
4284 .wfn = cmd_spoolss_getdriverdir,
4285 .table = &ndr_table_spoolss,
4286 .rpc_pipe = NULL,
4287 .description = "Get print driver upload directory",
4288 .usage = "",
4291 .name = "getdriverpackagepath",
4292 .returntype = RPC_RTYPE_WERROR,
4293 .ntfn = NULL,
4294 .wfn = cmd_spoolss_getdriverpackagepath,
4295 .table = &ndr_table_spoolss,
4296 .rpc_pipe = NULL,
4297 .description = "Get print driver package download directory",
4298 .usage = "",
4301 .name = "getprinter",
4302 .returntype = RPC_RTYPE_WERROR,
4303 .ntfn = NULL,
4304 .wfn = cmd_spoolss_getprinter,
4305 .table = &ndr_table_spoolss,
4306 .rpc_pipe = NULL,
4307 .description = "Get printer info",
4308 .usage = "",
4311 .name = "openprinter",
4312 .returntype = RPC_RTYPE_WERROR,
4313 .ntfn = NULL,
4314 .wfn = cmd_spoolss_open_printer,
4315 .table = &ndr_table_spoolss,
4316 .rpc_pipe = NULL,
4317 .description = "Open printer handle",
4318 .usage = "",
4321 .name = "openprinter_ex",
4322 .returntype = RPC_RTYPE_WERROR,
4323 .ntfn = NULL,
4324 .wfn = cmd_spoolss_open_printer_ex,
4325 .table = &ndr_table_spoolss,
4326 .rpc_pipe = NULL,
4327 .description = "Open printer handle",
4328 .usage = "",
4331 .name = "setdriver",
4332 .returntype = RPC_RTYPE_WERROR,
4333 .ntfn = NULL,
4334 .wfn = cmd_spoolss_setdriver,
4335 .table = &ndr_table_spoolss,
4336 .rpc_pipe = NULL,
4337 .description = "Set printer driver",
4338 .usage = "",
4341 .name = "getprintprocdir",
4342 .returntype = RPC_RTYPE_WERROR,
4343 .ntfn = NULL,
4344 .wfn = cmd_spoolss_getprintprocdir,
4345 .table = &ndr_table_spoolss,
4346 .rpc_pipe = NULL,
4347 .description = "Get print processor directory",
4348 .usage = "",
4351 .name = "addform",
4352 .returntype = RPC_RTYPE_WERROR,
4353 .ntfn = NULL,
4354 .wfn = cmd_spoolss_addform,
4355 .table = &ndr_table_spoolss,
4356 .rpc_pipe = NULL,
4357 .description = "Add form",
4358 .usage = "",
4361 .name = "setform",
4362 .returntype = RPC_RTYPE_WERROR,
4363 .ntfn = NULL,
4364 .wfn = cmd_spoolss_setform,
4365 .table = &ndr_table_spoolss,
4366 .rpc_pipe = NULL,
4367 .description = "Set form",
4368 .usage = "",
4371 .name = "getform",
4372 .returntype = RPC_RTYPE_WERROR,
4373 .ntfn = NULL,
4374 .wfn = cmd_spoolss_getform,
4375 .table = &ndr_table_spoolss,
4376 .rpc_pipe = NULL,
4377 .description = "Get form",
4378 .usage = "",
4381 .name = "deleteform",
4382 .returntype = RPC_RTYPE_WERROR,
4383 .ntfn = NULL,
4384 .wfn = cmd_spoolss_deleteform,
4385 .table = &ndr_table_spoolss,
4386 .rpc_pipe = NULL,
4387 .description = "Delete form",
4388 .usage = "",
4391 .name = "enumforms",
4392 .returntype = RPC_RTYPE_WERROR,
4393 .ntfn = NULL,
4394 .wfn = cmd_spoolss_enum_forms,
4395 .table = &ndr_table_spoolss,
4396 .rpc_pipe = NULL,
4397 .description = "Enumerate forms",
4398 .usage = "",
4401 .name = "setprinter",
4402 .returntype = RPC_RTYPE_WERROR,
4403 .ntfn = NULL,
4404 .wfn = cmd_spoolss_setprinter,
4405 .table = &ndr_table_spoolss,
4406 .rpc_pipe = NULL,
4407 .description = "Set printer comment",
4408 .usage = "",
4411 .name = "setprintername",
4412 .returntype = RPC_RTYPE_WERROR,
4413 .ntfn = NULL,
4414 .wfn = cmd_spoolss_setprintername,
4415 .table = &ndr_table_spoolss,
4416 .rpc_pipe = NULL,
4417 .description = "Set printername",
4418 .usage = "",
4421 .name = "setprinterdata",
4422 .returntype = RPC_RTYPE_WERROR,
4423 .ntfn = NULL,
4424 .wfn = cmd_spoolss_setprinterdata,
4425 .table = &ndr_table_spoolss,
4426 .rpc_pipe = NULL,
4427 .description = "Set REG_SZ printer data",
4428 .usage = "",
4431 .name = "rffpcnex",
4432 .returntype = RPC_RTYPE_WERROR,
4433 .ntfn = NULL,
4434 .wfn = cmd_spoolss_rffpcnex,
4435 .table = &ndr_table_spoolss,
4436 .rpc_pipe = NULL,
4437 .description = "Rffpcnex test",
4438 .usage = "",
4441 .name = "printercmp",
4442 .returntype = RPC_RTYPE_WERROR,
4443 .ntfn = NULL,
4444 .wfn = cmd_spoolss_printercmp,
4445 .table = &ndr_table_spoolss,
4446 .rpc_pipe = NULL,
4447 .description = "Printer comparison test",
4448 .usage = "",
4451 .name = "enumprocs",
4452 .returntype = RPC_RTYPE_WERROR,
4453 .ntfn = NULL,
4454 .wfn = cmd_spoolss_enum_procs,
4455 .table = &ndr_table_spoolss,
4456 .rpc_pipe = NULL,
4457 .description = "Enumerate Print Processors",
4458 .usage = "",
4461 .name = "enumprocdatatypes",
4462 .returntype = RPC_RTYPE_WERROR,
4463 .ntfn = NULL,
4464 .wfn = cmd_spoolss_enum_proc_data_types,
4465 .table = &ndr_table_spoolss,
4466 .rpc_pipe = NULL,
4467 .description = "Enumerate Print Processor Data Types",
4468 .usage = "",
4471 .name = "enummonitors",
4472 .returntype = RPC_RTYPE_WERROR,
4473 .ntfn = NULL,
4474 .wfn = cmd_spoolss_enum_monitors,
4475 .table = &ndr_table_spoolss,
4476 .rpc_pipe = NULL,
4477 .description = "Enumerate Print Monitors",
4478 .usage = "",
4481 .name = "createprinteric",
4482 .returntype = RPC_RTYPE_WERROR,
4483 .ntfn = NULL,
4484 .wfn = cmd_spoolss_create_printer_ic,
4485 .table = &ndr_table_spoolss,
4486 .rpc_pipe = NULL,
4487 .description = "Create Printer IC",
4488 .usage = "",
4491 .name = "playgdiscriptonprinteric",
4492 .returntype = RPC_RTYPE_WERROR,
4493 .ntfn = NULL,
4494 .wfn = cmd_spoolss_play_gdi_script_on_printer_ic,
4495 .table = &ndr_table_spoolss,
4496 .rpc_pipe = NULL,
4497 .description = "Create Printer IC",
4498 .usage = "",
4501 .name = "getcoreprinterdrivers",
4502 .returntype = RPC_RTYPE_WERROR,
4503 .ntfn = NULL,
4504 .wfn = cmd_spoolss_get_core_printer_drivers,
4505 .table = &ndr_table_spoolss,
4506 .rpc_pipe = NULL,
4507 .description = "Get CorePrinterDriver",
4508 .usage = "",
4511 .name = "enumpermachineconnections",
4512 .returntype = RPC_RTYPE_WERROR,
4513 .ntfn = NULL,
4514 .wfn = cmd_spoolss_enum_permachineconnections,
4515 .table = &ndr_table_spoolss,
4516 .rpc_pipe = NULL,
4517 .description = "Enumerate Per Machine Connections",
4518 .usage = "",
4521 .name = "addpermachineconnection",
4522 .returntype = RPC_RTYPE_WERROR,
4523 .ntfn = NULL,
4524 .wfn = cmd_spoolss_add_permachineconnection,
4525 .table = &ndr_table_spoolss,
4526 .rpc_pipe = NULL,
4527 .description = "Add Per Machine Connection",
4528 .usage = "",
4531 .name = "delpermachineconnection",
4532 .returntype = RPC_RTYPE_WERROR,
4533 .ntfn = NULL,
4534 .wfn = cmd_spoolss_del_permachineconnection,
4535 .table = &ndr_table_spoolss,
4536 .rpc_pipe = NULL,
4537 .description = "Delete Per Machine Connection",
4538 .usage = "",
4541 .name = NULL,