source: vendor/3.6.0/source3/rpcclient/cmd_spoolss.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

File size: 101.5 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
4
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
10
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.
15
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.
20
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/>.
23*/
24
25#include "includes.h"
26#include "rpcclient.h"
27#include "../librpc/gen_ndr/ndr_spoolss_c.h"
28#include "rpc_client/cli_spoolss.h"
29#include "rpc_client/init_spoolss.h"
30#include "registry/reg_objects.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
37#define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
38{ \
39 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
40 _cli->srv_name_slash, _arg); \
41 W_ERROR_HAVE_NO_MEMORY(_printername); \
42}
43
44/* The version int is used by getdrivers. Note that
45 all architecture strings that support mutliple
46 versions must be grouped together since enumdrivers
47 uses this property to prevent issuing multiple
48 enumdriver calls for the same arch */
49
50
51static const struct print_architecture_table_node archi_table[]= {
52
53 {"Windows 4.0", "WIN40", 0 },
54 {"Windows NT x86", "W32X86", 2 },
55 {"Windows NT x86", "W32X86", 3 },
56 {"Windows NT R4000", "W32MIPS", 2 },
57 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
58 {"Windows NT PowerPC", "W32PPC", 2 },
59 {"Windows IA64", "IA64", 3 },
60 {"Windows x64", "x64", 3 },
61 {NULL, "", -1 }
62};
63
64/**
65 * @file
66 *
67 * rpcclient module for SPOOLSS rpc pipe.
68 *
69 * This generally just parses and checks command lines, and then calls
70 * a cli_spoolss function.
71 **/
72
73/****************************************************************************
74 function to do the mapping between the long architecture name and
75 the short one.
76****************************************************************************/
77
78static const char *cmd_spoolss_get_short_archi(const char *long_archi)
79{
80 int i=-1;
81
82 DEBUG(107,("Getting architecture dependent directory\n"));
83 do {
84 i++;
85 } while ( (archi_table[i].long_archi!=NULL ) &&
86 StrCaseCmp(long_archi, archi_table[i].long_archi) );
87
88 if (archi_table[i].long_archi==NULL) {
89 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
90 return NULL;
91 }
92
93 /* this might be client code - but shouldn't this be an fstrcpy etc? */
94
95
96 DEBUGADD(108,("index: [%d]\n", i));
97 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
98 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
99
100 return archi_table[i].short_archi;
101}
102
103/****************************************************************************
104****************************************************************************/
105
106static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
107 TALLOC_CTX *mem_ctx,
108 int argc, const char **argv)
109{
110 WERROR werror;
111 struct policy_handle hnd;
112 uint32_t access_mask = PRINTER_ALL_ACCESS;
113 struct dcerpc_binding_handle *b = cli->binding_handle;
114
115 if (argc < 2) {
116 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
117 return WERR_OK;
118 }
119
120 if (argc >= 3) {
121 sscanf(argv[2], "%x", &access_mask);
122 }
123
124 /* Open the printer handle */
125
126 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
127 argv[1],
128 access_mask,
129 &hnd);
130 if (W_ERROR_IS_OK(werror)) {
131 printf("Printer %s opened successfully\n", argv[1]);
132 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
133
134 if (!W_ERROR_IS_OK(werror)) {
135 printf("Error closing printer handle! (%s)\n",
136 get_dos_error_msg(werror));
137 }
138 }
139
140 return werror;
141}
142
143/****************************************************************************
144****************************************************************************/
145
146static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
147 TALLOC_CTX *mem_ctx,
148 int argc, const char **argv)
149{
150 WERROR werror;
151 struct policy_handle hnd;
152 uint32_t access_mask = PRINTER_ALL_ACCESS;
153 NTSTATUS status;
154 struct spoolss_DevmodeContainer devmode_ctr;
155 struct dcerpc_binding_handle *b = cli->binding_handle;
156
157 ZERO_STRUCT(devmode_ctr);
158
159 if (argc < 2) {
160 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
161 return WERR_OK;
162 }
163
164 if (argc >= 3) {
165 sscanf(argv[2], "%x", &access_mask);
166 }
167
168 /* Open the printer handle */
169
170 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
171 argv[1],
172 NULL,
173 devmode_ctr,
174 access_mask,
175 &hnd,
176 &werror);
177 if (!NT_STATUS_IS_OK(status)) {
178 return ntstatus_to_werror(status);
179 }
180 if (W_ERROR_IS_OK(werror)) {
181 printf("Printer %s opened successfully\n", argv[1]);
182 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
183
184 if (!W_ERROR_IS_OK(werror)) {
185 printf("Error closing printer handle! (%s)\n",
186 get_dos_error_msg(werror));
187 }
188 }
189
190 return werror;
191}
192
193/****************************************************************************
194****************************************************************************/
195
196static void display_print_info0(struct spoolss_PrinterInfo0 *r)
197{
198 if (!r)
199 return;
200
201 printf("\tprintername:[%s]\n", r->printername);
202 printf("\tservername:[%s]\n", r->servername);
203 printf("\tcjobs:[0x%x]\n", r->cjobs);
204 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
205 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
206 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
207 r->time.day, r->time.day_of_week);
208 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
209 r->time.second, r->time.millisecond);
210
211 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
212 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
213
214 printf("\tversion:[0x%x]\n", r->version);
215 printf("\tfree_build:[0x%x]\n", r->free_build);
216 printf("\tspooling:[0x%x]\n", r->spooling);
217 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
218 printf("\tsession_counter:[0x%x]\n", r->session_counter);
219 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
220 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
221 printf("\tjob_error:[0x%x]\n", r->job_error);
222 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
223 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
224 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
225 printf("\tchange_id:[0x%x]\n", r->change_id);
226 printf("\tlast_error: %s\n", win_errstr(r->last_error));
227 printf("\tstatus:[0x%x]\n", r->status);
228 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
229 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
230 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
231 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
232 printf("\tref_ic:[0x%x]\n", r->ref_ic);
233 printf("\treserved2:[0x%x]\n", r->reserved2);
234 printf("\treserved3:[0x%x]\n", r->reserved3);
235
236 printf("\n");
237}
238
239/****************************************************************************
240****************************************************************************/
241
242static void display_print_info1(struct spoolss_PrinterInfo1 *r)
243{
244 printf("\tflags:[0x%x]\n", r->flags);
245 printf("\tname:[%s]\n", r->name);
246 printf("\tdescription:[%s]\n", r->description);
247 printf("\tcomment:[%s]\n", r->comment);
248
249 printf("\n");
250}
251
252/****************************************************************************
253****************************************************************************/
254
255static void display_print_info2(struct spoolss_PrinterInfo2 *r)
256{
257 printf("\tservername:[%s]\n", r->servername);
258 printf("\tprintername:[%s]\n", r->printername);
259 printf("\tsharename:[%s]\n", r->sharename);
260 printf("\tportname:[%s]\n", r->portname);
261 printf("\tdrivername:[%s]\n", r->drivername);
262 printf("\tcomment:[%s]\n", r->comment);
263 printf("\tlocation:[%s]\n", r->location);
264 printf("\tsepfile:[%s]\n", r->sepfile);
265 printf("\tprintprocessor:[%s]\n", r->printprocessor);
266 printf("\tdatatype:[%s]\n", r->datatype);
267 printf("\tparameters:[%s]\n", r->parameters);
268 printf("\tattributes:[0x%x]\n", r->attributes);
269 printf("\tpriority:[0x%x]\n", r->priority);
270 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
271 printf("\tstarttime:[0x%x]\n", r->starttime);
272 printf("\tuntiltime:[0x%x]\n", r->untiltime);
273 printf("\tstatus:[0x%x]\n", r->status);
274 printf("\tcjobs:[0x%x]\n", r->cjobs);
275 printf("\taverageppm:[0x%x]\n", r->averageppm);
276
277 if (r->secdesc)
278 display_sec_desc(r->secdesc);
279
280 printf("\n");
281}
282
283/****************************************************************************
284****************************************************************************/
285
286static void display_print_info3(struct spoolss_PrinterInfo3 *r)
287{
288 display_sec_desc(r->secdesc);
289
290 printf("\n");
291}
292
293/****************************************************************************
294****************************************************************************/
295
296static void display_print_info4(struct spoolss_PrinterInfo4 *r)
297{
298 printf("\tservername:[%s]\n", r->servername);
299 printf("\tprintername:[%s]\n", r->printername);
300 printf("\tattributes:[0x%x]\n", r->attributes);
301 printf("\n");
302}
303
304/****************************************************************************
305****************************************************************************/
306
307static void display_print_info5(struct spoolss_PrinterInfo5 *r)
308{
309 printf("\tprintername:[%s]\n", r->printername);
310 printf("\tportname:[%s]\n", r->portname);
311 printf("\tattributes:[0x%x]\n", r->attributes);
312 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
313 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
314 printf("\n");
315}
316
317/****************************************************************************
318****************************************************************************/
319
320static void display_print_info6(struct spoolss_PrinterInfo6 *r)
321{
322 printf("\tstatus:[0x%x]\n", r->status);
323 printf("\n");
324}
325
326/****************************************************************************
327****************************************************************************/
328
329static void display_print_info7(struct spoolss_PrinterInfo7 *r)
330{
331 printf("\tguid:[%s]\n", r->guid);
332 printf("\taction:[0x%x]\n", r->action);
333 printf("\n");
334}
335
336/****************************************************************************
337****************************************************************************/
338
339static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
340 TALLOC_CTX *mem_ctx,
341 int argc, const char **argv)
342{
343 WERROR result;
344 uint32_t level = 1;
345 union spoolss_PrinterInfo *info;
346 uint32_t i, count;
347 const char *name;
348 uint32_t flags = PRINTER_ENUM_LOCAL;
349
350 if (argc > 4) {
351 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
352 return WERR_OK;
353 }
354
355 if (argc >= 2) {
356 level = atoi(argv[1]);
357 }
358
359 if (argc >= 3) {
360 name = argv[2];
361 } else {
362 name = cli->srv_name_slash;
363 }
364
365 if (argc == 4) {
366 flags = atoi(argv[3]);
367 }
368
369 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
370 flags,
371 name,
372 level,
373 0,
374 &count,
375 &info);
376 if (W_ERROR_IS_OK(result)) {
377
378 if (!count) {
379 printf ("No printers returned.\n");
380 goto done;
381 }
382
383 for (i = 0; i < count; i++) {
384 switch (level) {
385 case 0:
386 display_print_info0(&info[i].info0);
387 break;
388 case 1:
389 display_print_info1(&info[i].info1);
390 break;
391 case 2:
392 display_print_info2(&info[i].info2);
393 break;
394 case 3:
395 display_print_info3(&info[i].info3);
396 break;
397 case 4:
398 display_print_info4(&info[i].info4);
399 break;
400 case 5:
401 display_print_info5(&info[i].info5);
402 break;
403 case 6:
404 display_print_info6(&info[i].info6);
405 break;
406 default:
407 printf("unknown info level %d\n", level);
408 goto done;
409 }
410 }
411 }
412 done:
413
414 return result;
415}
416
417/****************************************************************************
418****************************************************************************/
419
420static void display_port_info_1(struct spoolss_PortInfo1 *r)
421{
422 printf("\tPort Name:\t[%s]\n", r->port_name);
423}
424
425/****************************************************************************
426****************************************************************************/
427
428static void display_port_info_2(struct spoolss_PortInfo2 *r)
429{
430 printf("\tPort Name:\t[%s]\n", r->port_name);
431 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
432 printf("\tDescription:\t[%s]\n", r->description);
433 printf("\tPort Type:\t" );
434 if (r->port_type) {
435 int comma = 0; /* hack */
436 printf( "[" );
437 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
438 printf( "Read" );
439 comma = 1;
440 }
441 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
442 printf( "%sWrite", comma ? ", " : "" );
443 comma = 1;
444 }
445 /* These two have slightly different interpretations
446 on 95/98/ME but I'm disregarding that for now */
447 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
448 printf( "%sRedirected", comma ? ", " : "" );
449 comma = 1;
450 }
451 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
452 printf( "%sNet-Attached", comma ? ", " : "" );
453 }
454 printf( "]\n" );
455 } else {
456 printf( "[Unset]\n" );
457 }
458 printf("\tReserved:\t[%d]\n", r->reserved);
459 printf("\n");
460}
461
462/****************************************************************************
463****************************************************************************/
464
465static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
466 TALLOC_CTX *mem_ctx, int argc,
467 const char **argv)
468{
469 WERROR result;
470 uint32_t level = 1;
471 uint32_t count;
472 union spoolss_PortInfo *info;
473
474 if (argc > 2) {
475 printf("Usage: %s [level]\n", argv[0]);
476 return WERR_OK;
477 }
478
479 if (argc == 2) {
480 level = atoi(argv[1]);
481 }
482
483 /* Enumerate ports */
484
485 result = rpccli_spoolss_enumports(cli, mem_ctx,
486 cli->srv_name_slash,
487 level,
488 0,
489 &count,
490 &info);
491 if (W_ERROR_IS_OK(result)) {
492 int i;
493
494 for (i = 0; i < count; i++) {
495 switch (level) {
496 case 1:
497 display_port_info_1(&info[i].info1);
498 break;
499 case 2:
500 display_port_info_2(&info[i].info2);
501 break;
502 default:
503 printf("unknown info level %d\n", level);
504 break;
505 }
506 }
507 }
508
509 return result;
510}
511
512/****************************************************************************
513****************************************************************************/
514
515static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
516 TALLOC_CTX *mem_ctx,
517 int argc, const char **argv)
518{
519 struct policy_handle pol;
520 WERROR result;
521 NTSTATUS status;
522 uint32_t info_level = 2;
523 union spoolss_PrinterInfo info;
524 struct spoolss_SetPrinterInfoCtr info_ctr;
525 struct spoolss_SetPrinterInfo2 info2;
526 const char *printername, *comment = NULL;
527 struct spoolss_DevmodeContainer devmode_ctr;
528 struct sec_desc_buf secdesc_ctr;
529 struct dcerpc_binding_handle *b = cli->binding_handle;
530
531 if (argc == 1 || argc > 3) {
532 printf("Usage: %s printername comment\n", argv[0]);
533
534 return WERR_OK;
535 }
536
537 /* Open a printer handle */
538 if (argc == 3) {
539 comment = argv[2];
540 }
541
542 ZERO_STRUCT(devmode_ctr);
543 ZERO_STRUCT(secdesc_ctr);
544
545 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
546
547 /* get a printer handle */
548 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
549 printername,
550 PRINTER_ALL_ACCESS,
551 &pol);
552 if (!W_ERROR_IS_OK(result))
553 goto done;
554
555 /* Get printer info */
556 result = rpccli_spoolss_getprinter(cli, mem_ctx,
557 &pol,
558 info_level,
559 0,
560 &info);
561 if (!W_ERROR_IS_OK(result))
562 goto done;
563
564
565 /* Modify the comment. */
566 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
567 info2.comment = comment;
568
569 info_ctr.level = 2;
570 info_ctr.info.info2 = &info2;
571
572 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
573 &pol,
574 &info_ctr,
575 &devmode_ctr,
576 &secdesc_ctr,
577 0, /* command */
578 &result);
579 if (!NT_STATUS_IS_OK(status)) {
580 result = ntstatus_to_werror(status);
581 goto done;
582 }
583 if (W_ERROR_IS_OK(result))
584 printf("Success in setting comment.\n");
585
586 done:
587 if (is_valid_policy_hnd(&pol)) {
588 WERROR _result;
589 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
590 }
591
592 return result;
593}
594
595/****************************************************************************
596****************************************************************************/
597
598static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
599 TALLOC_CTX *mem_ctx,
600 int argc, const char **argv)
601{
602 struct policy_handle pol;
603 WERROR result;
604 NTSTATUS status;
605 uint32_t info_level = 2;
606 union spoolss_PrinterInfo info;
607 const char *printername,
608 *new_printername = NULL;
609 struct spoolss_SetPrinterInfoCtr info_ctr;
610 struct spoolss_SetPrinterInfo2 info2;
611 struct spoolss_DevmodeContainer devmode_ctr;
612 struct sec_desc_buf secdesc_ctr;
613 struct dcerpc_binding_handle *b = cli->binding_handle;
614
615 ZERO_STRUCT(devmode_ctr);
616 ZERO_STRUCT(secdesc_ctr);
617
618 if (argc == 1 || argc > 3) {
619 printf("Usage: %s printername new_printername\n", argv[0]);
620
621 return WERR_OK;
622 }
623
624 /* Open a printer handle */
625 if (argc == 3) {
626 new_printername = argv[2];
627 }
628
629 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
630
631 /* get a printer handle */
632 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
633 printername,
634 PRINTER_ALL_ACCESS,
635 &pol);
636 if (!W_ERROR_IS_OK(result))
637 goto done;
638
639 /* Get printer info */
640 result = rpccli_spoolss_getprinter(cli, mem_ctx,
641 &pol,
642 info_level,
643 0,
644 &info);
645 if (!W_ERROR_IS_OK(result))
646 goto done;
647
648 /* Modify the printername. */
649 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
650 info2.printername = new_printername;
651
652 info_ctr.level = 2;
653 info_ctr.info.info2 = &info2;
654
655 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
656 &pol,
657 &info_ctr,
658 &devmode_ctr,
659 &secdesc_ctr,
660 0, /* command */
661 &result);
662 if (!NT_STATUS_IS_OK(status)) {
663 result = ntstatus_to_werror(status);
664 goto done;
665 }
666 if (W_ERROR_IS_OK(result))
667 printf("Success in setting printername.\n");
668
669 done:
670 if (is_valid_policy_hnd(&pol)) {
671 WERROR _result;
672 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
673 }
674
675 return result;
676}
677
678/****************************************************************************
679****************************************************************************/
680
681static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
682 TALLOC_CTX *mem_ctx,
683 int argc, const char **argv)
684{
685 struct policy_handle pol;
686 WERROR result;
687 uint32_t level = 1;
688 const char *printername;
689 union spoolss_PrinterInfo info;
690 struct dcerpc_binding_handle *b = cli->binding_handle;
691
692 if (argc == 1 || argc > 3) {
693 printf("Usage: %s <printername> [level]\n", argv[0]);
694 return WERR_OK;
695 }
696
697 /* Open a printer handle */
698 if (argc == 3) {
699 level = atoi(argv[2]);
700 }
701
702 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
703
704 /* get a printer handle */
705
706 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
707 printername,
708 SEC_FLAG_MAXIMUM_ALLOWED,
709 &pol);
710 if (!W_ERROR_IS_OK(result)) {
711 goto done;
712 }
713
714 /* Get printer info */
715
716 result = rpccli_spoolss_getprinter(cli, mem_ctx,
717 &pol,
718 level,
719 0,
720 &info);
721 if (!W_ERROR_IS_OK(result)) {
722 goto done;
723 }
724
725 /* Display printer info */
726 switch (level) {
727 case 0:
728 display_print_info0(&info.info0);
729 break;
730 case 1:
731 display_print_info1(&info.info1);
732 break;
733 case 2:
734 display_print_info2(&info.info2);
735 break;
736 case 3:
737 display_print_info3(&info.info3);
738 break;
739 case 4:
740 display_print_info4(&info.info4);
741 break;
742 case 5:
743 display_print_info5(&info.info5);
744 break;
745 case 6:
746 display_print_info6(&info.info6);
747 break;
748 case 7:
749 display_print_info7(&info.info7);
750 break;
751 default:
752 printf("unknown info level %d\n", level);
753 break;
754 }
755 done:
756 if (is_valid_policy_hnd(&pol)) {
757 WERROR _result;
758 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
759 }
760
761 return result;
762}
763
764/****************************************************************************
765****************************************************************************/
766
767static void display_reg_value(struct regval_blob *value)
768{
769 const char *text = NULL;
770 DATA_BLOB blob;
771
772 switch(regval_type(value)) {
773 case REG_DWORD:
774 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
775 *((uint32_t *) regval_data_p(value)));
776 break;
777 case REG_SZ:
778 blob = data_blob_const(regval_data_p(value), regval_size(value));
779 pull_reg_sz(talloc_tos(), &blob, &text);
780 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
781 break;
782 case REG_BINARY: {
783 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
784 size_t i, len;
785 printf("%s: REG_BINARY:", regval_name(value));
786 len = strlen(hex);
787 for (i=0; i<len; i++) {
788 if (hex[i] == '\0') {
789 break;
790 }
791 if (i%40 == 0) {
792 putchar('\n');
793 }
794 putchar(hex[i]);
795 }
796 TALLOC_FREE(hex);
797 putchar('\n');
798 break;
799 }
800 case REG_MULTI_SZ: {
801 uint32_t i;
802 const char **values;
803 blob = data_blob_const(regval_data_p(value), regval_size(value));
804
805 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
806 d_printf("pull_reg_multi_sz failed\n");
807 break;
808 }
809
810 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
811 for (i=0; values[i] != NULL; i++) {
812 d_printf("%s\n", values[i]);
813 }
814 TALLOC_FREE(values);
815 break;
816 }
817 default:
818 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
819 }
820
821}
822
823/****************************************************************************
824****************************************************************************/
825
826static void display_printer_data(const char *v,
827 enum winreg_Type type,
828 uint8_t *data,
829 uint32_t length)
830{
831 int i;
832 union spoolss_PrinterData r;
833 DATA_BLOB blob = data_blob_const(data, length);
834 WERROR result;
835
836 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
837 if (!W_ERROR_IS_OK(result)) {
838 return;
839 }
840
841 switch (type) {
842 case REG_DWORD:
843 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
844 break;
845 case REG_SZ:
846 printf("%s: REG_SZ: %s\n", v, r.string);
847 break;
848 case REG_BINARY: {
849 char *hex = hex_encode_talloc(NULL,
850 r.binary.data, r.binary.length);
851 size_t len;
852 printf("%s: REG_BINARY:", v);
853 len = strlen(hex);
854 for (i=0; i<len; i++) {
855 if (hex[i] == '\0') {
856 break;
857 }
858 if (i%40 == 0) {
859 putchar('\n');
860 }
861 putchar(hex[i]);
862 }
863 TALLOC_FREE(hex);
864 putchar('\n');
865 break;
866 }
867 case REG_MULTI_SZ:
868 printf("%s: REG_MULTI_SZ: ", v);
869 for (i=0; r.string_array[i] != NULL; i++) {
870 printf("%s ", r.string_array[i]);
871 }
872 printf("\n");
873 break;
874 default:
875 printf("%s: unknown type 0x%02x:\n", v, type);
876 break;
877 }
878}
879
880/****************************************************************************
881****************************************************************************/
882
883static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
884 TALLOC_CTX *mem_ctx,
885 int argc, const char **argv)
886{
887 struct policy_handle pol;
888 WERROR result;
889 fstring printername;
890 const char *valuename;
891 enum winreg_Type type;
892 uint8_t *data;
893 uint32_t needed;
894 struct dcerpc_binding_handle *b = cli->binding_handle;
895
896 if (argc != 3) {
897 printf("Usage: %s <printername> <valuename>\n", argv[0]);
898 printf("<printername> of . queries print server\n");
899 return WERR_OK;
900 }
901 valuename = argv[2];
902
903 /* Open a printer handle */
904
905 if (strncmp(argv[1], ".", sizeof(".")) == 0)
906 fstrcpy(printername, cli->srv_name_slash);
907 else
908 slprintf(printername, sizeof(printername)-1, "%s\\%s",
909 cli->srv_name_slash, argv[1]);
910
911 /* get a printer handle */
912
913 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
914 printername,
915 SEC_FLAG_MAXIMUM_ALLOWED,
916 &pol);
917 if (!W_ERROR_IS_OK(result))
918 goto done;
919
920 /* Get printer info */
921
922 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
923 &pol,
924 valuename,
925 0,
926 &type,
927 &needed,
928 &data);
929 if (!W_ERROR_IS_OK(result))
930 goto done;
931
932 /* Display printer data */
933
934 display_printer_data(valuename, type, data, needed);
935
936 done:
937 if (is_valid_policy_hnd(&pol)) {
938 WERROR _result;
939 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
940 }
941
942 return result;
943}
944
945/****************************************************************************
946****************************************************************************/
947
948static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
949 TALLOC_CTX *mem_ctx,
950 int argc, const char **argv)
951{
952 struct policy_handle pol;
953 WERROR result;
954 NTSTATUS status;
955 fstring printername;
956 const char *valuename, *keyname;
957
958 enum winreg_Type type;
959 uint8_t *data = NULL;
960 uint32_t offered = 0;
961 uint32_t needed;
962 struct dcerpc_binding_handle *b = cli->binding_handle;
963
964 if (argc != 4) {
965 printf("Usage: %s <printername> <keyname> <valuename>\n",
966 argv[0]);
967 printf("<printername> of . queries print server\n");
968 return WERR_OK;
969 }
970 valuename = argv[3];
971 keyname = argv[2];
972
973 /* Open a printer handle */
974
975 if (strncmp(argv[1], ".", sizeof(".")) == 0)
976 fstrcpy(printername, cli->srv_name_slash);
977 else
978 slprintf(printername, sizeof(printername)-1, "%s\\%s",
979 cli->srv_name_slash, argv[1]);
980
981 /* get a printer handle */
982
983 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
984 printername,
985 SEC_FLAG_MAXIMUM_ALLOWED,
986 &pol);
987 if (!W_ERROR_IS_OK(result))
988 goto done;
989
990 /* Get printer info */
991
992 data = talloc_zero_array(mem_ctx, uint8_t, offered);
993 if (!data) {
994 goto done;
995 }
996
997 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
998 &pol,
999 keyname,
1000 valuename,
1001 &type,
1002 data,
1003 offered,
1004 &needed,
1005 &result);
1006 if (!NT_STATUS_IS_OK(status)) {
1007 result = ntstatus_to_werror(status);
1008 goto done;
1009 }
1010 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1011 offered = needed;
1012 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1013 if (!data) {
1014 goto done;
1015 }
1016 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1017 &pol,
1018 keyname,
1019 valuename,
1020 &type,
1021 data,
1022 offered,
1023 &needed,
1024 &result);
1025 }
1026
1027 if (!NT_STATUS_IS_OK(status)) {
1028 result = ntstatus_to_werror(status);
1029 goto done;
1030 }
1031
1032 if (!W_ERROR_IS_OK(result))
1033 goto done;
1034
1035 /* Display printer data */
1036
1037 display_printer_data(valuename, type, data, needed);
1038
1039
1040 done:
1041 if (is_valid_policy_hnd(&pol)) {
1042 WERROR _result;
1043 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1044 }
1045
1046 return result;
1047}
1048
1049/****************************************************************************
1050****************************************************************************/
1051
1052static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1053{
1054 if (!r) {
1055 return;
1056 }
1057
1058 printf("Printer Driver Info 1:\n");
1059 printf("\tDriver Name: [%s]\n", r->driver_name);
1060 printf("\n");
1061}
1062
1063/****************************************************************************
1064****************************************************************************/
1065
1066static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1067{
1068 if (!r) {
1069 return;
1070 }
1071
1072 printf("Printer Driver Info 2:\n");
1073 printf("\tVersion: [%x]\n", r->version);
1074 printf("\tDriver Name: [%s]\n", r->driver_name);
1075 printf("\tArchitecture: [%s]\n", r->architecture);
1076 printf("\tDriver Path: [%s]\n", r->driver_path);
1077 printf("\tDatafile: [%s]\n", r->data_file);
1078 printf("\tConfigfile: [%s]\n", r->config_file);
1079 printf("\n");
1080}
1081
1082/****************************************************************************
1083****************************************************************************/
1084
1085static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1086{
1087 int i;
1088
1089 if (!r) {
1090 return;
1091 }
1092
1093 printf("Printer Driver Info 3:\n");
1094 printf("\tVersion: [%x]\n", r->version);
1095 printf("\tDriver Name: [%s]\n", r->driver_name);
1096 printf("\tArchitecture: [%s]\n", r->architecture);
1097 printf("\tDriver Path: [%s]\n", r->driver_path);
1098 printf("\tDatafile: [%s]\n", r->data_file);
1099 printf("\tConfigfile: [%s]\n", r->config_file);
1100 printf("\tHelpfile: [%s]\n", r->help_file);
1101
1102 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1103 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1104 }
1105
1106 printf("\tMonitorname: [%s]\n", r->monitor_name);
1107 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1108 printf("\n");
1109}
1110
1111/****************************************************************************
1112****************************************************************************/
1113
1114static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1115{
1116 int i;
1117
1118 if (!r) {
1119 return;
1120 }
1121
1122 printf("Printer Driver Info 4:\n");
1123 printf("\tVersion: [%x]\n", r->version);
1124 printf("\tDriver Name: [%s]\n", r->driver_name);
1125 printf("\tArchitecture: [%s]\n", r->architecture);
1126 printf("\tDriver Path: [%s]\n", r->driver_path);
1127 printf("\tDatafile: [%s]\n", r->data_file);
1128 printf("\tConfigfile: [%s]\n", r->config_file);
1129 printf("\tHelpfile: [%s]\n", r->help_file);
1130
1131 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1132 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1133 }
1134
1135 printf("\tMonitorname: [%s]\n", r->monitor_name);
1136 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1137
1138 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1139 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1140 }
1141 printf("\n");
1142}
1143
1144/****************************************************************************
1145****************************************************************************/
1146
1147static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1148{
1149 if (!r) {
1150 return;
1151 }
1152
1153 printf("Printer Driver Info 5:\n");
1154 printf("\tVersion: [%x]\n", r->version);
1155 printf("\tDriver Name: [%s]\n", r->driver_name);
1156 printf("\tArchitecture: [%s]\n", r->architecture);
1157 printf("\tDriver Path: [%s]\n", r->driver_path);
1158 printf("\tDatafile: [%s]\n", r->data_file);
1159 printf("\tConfigfile: [%s]\n", r->config_file);
1160 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1161 printf("\tConfig Version: [0x%x]\n", r->config_version);
1162 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1163 printf("\n");
1164}
1165
1166/****************************************************************************
1167****************************************************************************/
1168
1169static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1170{
1171 int i;
1172
1173 if (!r) {
1174 return;
1175 }
1176
1177 printf("Printer Driver Info 6:\n");
1178 printf("\tVersion: [%x]\n", r->version);
1179 printf("\tDriver Name: [%s]\n", r->driver_name);
1180 printf("\tArchitecture: [%s]\n", r->architecture);
1181 printf("\tDriver Path: [%s]\n", r->driver_path);
1182 printf("\tDatafile: [%s]\n", r->data_file);
1183 printf("\tConfigfile: [%s]\n", r->config_file);
1184 printf("\tHelpfile: [%s]\n", r->help_file);
1185
1186 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1187 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1188 }
1189
1190 printf("\tMonitorname: [%s]\n", r->monitor_name);
1191 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1192
1193 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1194 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1195 }
1196
1197 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1198 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1199 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1200 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1201 printf("\tHardware ID: [%s]\n", r->hardware_id);
1202 printf("\tProvider: [%s]\n", r->provider);
1203
1204 printf("\n");
1205}
1206
1207/****************************************************************************
1208****************************************************************************/
1209
1210static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1211{
1212 int i;
1213
1214 if (!r) {
1215 return;
1216 }
1217
1218 printf("Printer Driver Info 8:\n");
1219 printf("\tVersion: [%x]\n", r->version);
1220 printf("\tDriver Name: [%s]\n", r->driver_name);
1221 printf("\tArchitecture: [%s]\n", r->architecture);
1222 printf("\tDriver Path: [%s]\n", r->driver_path);
1223 printf("\tDatafile: [%s]\n", r->data_file);
1224 printf("\tConfigfile: [%s]\n", r->config_file);
1225 printf("\tHelpfile: [%s]\n", r->help_file);
1226 printf("\tMonitorname: [%s]\n", r->monitor_name);
1227 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1228
1229 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1230 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1231 }
1232
1233 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1234 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1235 }
1236
1237 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1238 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1239 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1240 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1241 printf("\tHardware ID: [%s]\n", r->hardware_id);
1242 printf("\tProvider: [%s]\n", r->provider);
1243 printf("\tPrint Processor: [%s]\n", r->print_processor);
1244 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1245 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1246 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1247 }
1248 printf("\tInf Path: [%s]\n", r->inf_path);
1249 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1250 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1251 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1252 }
1253 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1254 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1255 (long long unsigned int)r->min_inbox_driver_ver_version);
1256
1257 printf("\n");
1258}
1259
1260/****************************************************************************
1261****************************************************************************/
1262
1263static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1264 TALLOC_CTX *mem_ctx,
1265 int argc, const char **argv)
1266{
1267 struct policy_handle pol;
1268 WERROR werror;
1269 uint32_t level = 3;
1270 const char *printername;
1271 uint32_t i;
1272 bool success = false;
1273 union spoolss_DriverInfo info;
1274 uint32_t server_major_version;
1275 uint32_t server_minor_version;
1276 struct dcerpc_binding_handle *b = cli->binding_handle;
1277
1278 if ((argc == 1) || (argc > 3)) {
1279 printf("Usage: %s <printername> [level]\n", argv[0]);
1280 return WERR_OK;
1281 }
1282
1283 /* get the arguments need to open the printer handle */
1284
1285 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1286
1287 if (argc == 3) {
1288 level = atoi(argv[2]);
1289 }
1290
1291 /* Open a printer handle */
1292
1293 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1294 printername,
1295 PRINTER_ACCESS_USE,
1296 &pol);
1297 if (!W_ERROR_IS_OK(werror)) {
1298 printf("Error opening printer handle for %s!\n", printername);
1299 return werror;
1300 }
1301
1302 /* loop through and print driver info level for each architecture */
1303
1304 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1305
1306 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1307 &pol,
1308 archi_table[i].long_archi,
1309 level,
1310 0, /* offered */
1311 archi_table[i].version,
1312 2,
1313 &info,
1314 &server_major_version,
1315 &server_minor_version);
1316 if (!W_ERROR_IS_OK(werror)) {
1317 continue;
1318 }
1319
1320 /* need at least one success */
1321
1322 success = true;
1323
1324 printf("\n[%s]\n", archi_table[i].long_archi);
1325
1326 switch (level) {
1327 case 1:
1328 display_print_driver1(&info.info1);
1329 break;
1330 case 2:
1331 display_print_driver2(&info.info2);
1332 break;
1333 case 3:
1334 display_print_driver3(&info.info3);
1335 break;
1336 case 4:
1337 display_print_driver4(&info.info4);
1338 break;
1339 case 5:
1340 display_print_driver5(&info.info5);
1341 break;
1342 case 6:
1343 display_print_driver6(&info.info6);
1344 break;
1345 case 8:
1346 display_print_driver8(&info.info8);
1347 break;
1348 default:
1349 printf("unknown info level %d\n", level);
1350 break;
1351 }
1352 }
1353
1354 /* Cleanup */
1355
1356 if (is_valid_policy_hnd(&pol)) {
1357 WERROR _result;
1358 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1359 }
1360
1361 if (success) {
1362 werror = WERR_OK;
1363 }
1364
1365 return werror;
1366}
1367
1368/****************************************************************************
1369****************************************************************************/
1370
1371static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1372 TALLOC_CTX *mem_ctx,
1373 const char *architecture,
1374 uint32_t level)
1375{
1376 WERROR werror;
1377 uint32_t count = 0;
1378 union spoolss_DriverInfo *info = NULL;
1379 uint32_t j;
1380
1381 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1382 cli->srv_name_slash,
1383 architecture,
1384 level,
1385 0,
1386 &count,
1387 &info);
1388
1389 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1390 printf("Server does not support environment [%s]\n",
1391 architecture);
1392 return WERR_OK;
1393 }
1394
1395 if (count == 0) {
1396 return WERR_OK;
1397 }
1398
1399 if (!W_ERROR_IS_OK(werror)) {
1400 printf("Error getting driver for environment [%s] - %s\n",
1401 architecture, win_errstr(werror));
1402 return werror;
1403 }
1404
1405 printf("\n[%s]\n", architecture);
1406
1407 switch (level) {
1408 case 1:
1409 for (j=0; j < count; j++) {
1410 display_print_driver1(&info[j].info1);
1411 }
1412 break;
1413 case 2:
1414 for (j=0; j < count; j++) {
1415 display_print_driver2(&info[j].info2);
1416 }
1417 break;
1418 case 3:
1419 for (j=0; j < count; j++) {
1420 display_print_driver3(&info[j].info3);
1421 }
1422 break;
1423 case 4:
1424 for (j=0; j < count; j++) {
1425 display_print_driver4(&info[j].info4);
1426 }
1427 break;
1428 case 5:
1429 for (j=0; j < count; j++) {
1430 display_print_driver5(&info[j].info5);
1431 }
1432 break;
1433 case 6:
1434 for (j=0; j < count; j++) {
1435 display_print_driver6(&info[j].info6);
1436 }
1437 break;
1438 case 8:
1439 for (j=0; j < count; j++) {
1440 display_print_driver8(&info[j].info8);
1441 }
1442 break;
1443 default:
1444 printf("unknown info level %d\n", level);
1445 return WERR_UNKNOWN_LEVEL;
1446 }
1447
1448 return werror;
1449}
1450
1451static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1452 TALLOC_CTX *mem_ctx,
1453 int argc, const char **argv)
1454{
1455 WERROR werror = WERR_OK;
1456 uint32_t level = 1;
1457 uint32_t i;
1458 const char *architecture = NULL;
1459
1460 if (argc > 3) {
1461 printf("Usage: enumdrivers [level] [architecture]\n");
1462 return WERR_OK;
1463 }
1464
1465 if (argc >= 2) {
1466 level = atoi(argv[1]);
1467 }
1468
1469 if (argc == 3) {
1470 architecture = argv[2];
1471 }
1472
1473 if (architecture) {
1474 return enum_driver_by_architecture(cli, mem_ctx,
1475 architecture,
1476 level);
1477 }
1478
1479 /* loop through and print driver info level for each architecture */
1480 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1481 /* check to see if we already asked for this architecture string */
1482
1483 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1484 continue;
1485 }
1486
1487 werror = enum_driver_by_architecture(cli, mem_ctx,
1488 archi_table[i].long_archi,
1489 level);
1490 if (!W_ERROR_IS_OK(werror)) {
1491 break;
1492 }
1493 }
1494
1495 return werror;
1496}
1497
1498/****************************************************************************
1499****************************************************************************/
1500
1501static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1502{
1503 printf("\tDirectory Name:[%s]\n", r->directory_name);
1504}
1505
1506/****************************************************************************
1507****************************************************************************/
1508
1509static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1510 TALLOC_CTX *mem_ctx,
1511 int argc, const char **argv)
1512{
1513 WERROR result;
1514 NTSTATUS status;
1515 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1516 DATA_BLOB buffer;
1517 uint32_t offered;
1518 union spoolss_DriverDirectoryInfo info;
1519 uint32_t needed;
1520 struct dcerpc_binding_handle *b = cli->binding_handle;
1521
1522 if (argc > 2) {
1523 printf("Usage: %s [environment]\n", argv[0]);
1524 return WERR_OK;
1525 }
1526
1527 /* Get the arguments need to open the printer handle */
1528
1529 if (argc == 2) {
1530 env = argv[1];
1531 }
1532
1533 /* Get the directory. Only use Info level 1 */
1534
1535 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1536 cli->srv_name_slash,
1537 env,
1538 1,
1539 NULL, /* buffer */
1540 0, /* offered */
1541 NULL, /* info */
1542 &needed,
1543 &result);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 return ntstatus_to_werror(status);
1546 }
1547 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1548 offered = needed;
1549 buffer = data_blob_talloc_zero(mem_ctx, needed);
1550
1551 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1552 cli->srv_name_slash,
1553 env,
1554 1,
1555 &buffer,
1556 offered,
1557 &info,
1558 &needed,
1559 &result);
1560 if (!NT_STATUS_IS_OK(status)) {
1561 return ntstatus_to_werror(status);
1562 }
1563 }
1564
1565 if (W_ERROR_IS_OK(result)) {
1566 display_printdriverdir_1(&info.info1);
1567 }
1568
1569 return result;
1570}
1571
1572/****************************************************************************
1573****************************************************************************/
1574
1575static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1576 struct spoolss_AddDriverInfo3 *info,
1577 const char *arch)
1578{
1579
1580 int i;
1581
1582 for (i=0; archi_table[i].long_archi != NULL; i++)
1583 {
1584 if (strcmp(arch, archi_table[i].short_archi) == 0)
1585 {
1586 info->version = archi_table[i].version;
1587 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1588 break;
1589 }
1590 }
1591
1592 if (archi_table[i].long_archi == NULL)
1593 {
1594 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1595 }
1596
1597 return;
1598}
1599
1600
1601/**************************************************************************
1602 wrapper for strtok to get the next parameter from a delimited list.
1603 Needed to handle the empty parameter string denoted by "NULL"
1604 *************************************************************************/
1605
1606static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1607 const char *delim, const char **dest,
1608 char **saveptr)
1609{
1610 char *ptr;
1611
1612 /* get the next token */
1613 ptr = strtok_r(str, delim, saveptr);
1614
1615 /* a string of 'NULL' is used to represent an empty
1616 parameter because two consecutive delimiters
1617 will not return an empty string. See man strtok(3)
1618 for details */
1619 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1620 ptr = NULL;
1621 }
1622
1623 if (dest != NULL) {
1624 *dest = talloc_strdup(mem_ctx, ptr);
1625 }
1626
1627 return ptr;
1628}
1629
1630/********************************************************************************
1631 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1632 string in the form of
1633 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1634 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1635 <Default Data Type>:<Comma Separated list of Files>
1636 *******************************************************************************/
1637
1638static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1639 char *args)
1640{
1641 char *str, *str2;
1642 int count = 0;
1643 char *saveptr = NULL;
1644 struct spoolss_StringArray *deps;
1645 const char **file_array = NULL;
1646 int i;
1647
1648 /* fill in the UNISTR fields */
1649 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1650 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1651 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1652 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1653 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1654 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1655 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1656
1657 /* <Comma Separated List of Dependent Files> */
1658 /* save the beginning of the string */
1659 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1660 str = str2;
1661
1662 /* begin to strip out each filename */
1663 str = strtok_r(str, ",", &saveptr);
1664
1665 /* no dependent files, we are done */
1666 if (!str) {
1667 return true;
1668 }
1669
1670 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1671 if (!deps) {
1672 return false;
1673 }
1674
1675 while (str != NULL) {
1676 add_string_to_array(deps, str, &file_array, &count);
1677 str = strtok_r(NULL, ",", &saveptr);
1678 }
1679
1680 deps->string = talloc_zero_array(deps, const char *, count + 1);
1681 if (!deps->string) {
1682 return false;
1683 }
1684
1685 for (i=0; i < count; i++) {
1686 deps->string[i] = file_array[i];
1687 }
1688
1689 r->dependent_files = deps;
1690
1691 return true;
1692}
1693
1694/****************************************************************************
1695****************************************************************************/
1696
1697static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1698 TALLOC_CTX *mem_ctx,
1699 int argc, const char **argv)
1700{
1701 WERROR result;
1702 NTSTATUS status;
1703 uint32_t level = 3;
1704 struct spoolss_AddDriverInfoCtr info_ctr;
1705 struct spoolss_AddDriverInfo3 info3;
1706 const char *arch;
1707 char *driver_args;
1708 struct dcerpc_binding_handle *b = cli->binding_handle;
1709
1710 /* parse the command arguments */
1711 if (argc != 3 && argc != 4)
1712 {
1713 printf ("Usage: %s <Environment> \\\n", argv[0]);
1714 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1715 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1716 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1717 printf ("\t[version]\n");
1718
1719 return WERR_OK;
1720 }
1721
1722 /* Fill in the spoolss_AddDriverInfo3 struct */
1723 ZERO_STRUCT(info3);
1724
1725 arch = cmd_spoolss_get_short_archi(argv[1]);
1726 if (!arch) {
1727 printf ("Error Unknown architecture [%s]\n", argv[1]);
1728 return WERR_INVALID_PARAM;
1729 }
1730
1731 set_drv_info_3_env(mem_ctx, &info3, arch);
1732
1733 driver_args = talloc_strdup( mem_ctx, argv[2] );
1734 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1735 {
1736 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1737 return WERR_INVALID_PARAM;
1738 }
1739
1740 /* if printer driver version specified, override the default version
1741 * used by the architecture. This allows installation of Windows
1742 * 2000 (version 3) printer drivers. */
1743 if (argc == 4)
1744 {
1745 info3.version = atoi(argv[3]);
1746 }
1747
1748
1749 info_ctr.level = level;
1750 info_ctr.info.info3 = &info3;
1751
1752 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1753 cli->srv_name_slash,
1754 &info_ctr,
1755 &result);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 return ntstatus_to_werror(status);
1758 }
1759 if (W_ERROR_IS_OK(result)) {
1760 printf ("Printer Driver %s successfully installed.\n",
1761 info3.driver_name);
1762 }
1763
1764 return result;
1765}
1766
1767
1768/****************************************************************************
1769****************************************************************************/
1770
1771static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1772 TALLOC_CTX *mem_ctx,
1773 int argc, const char **argv)
1774{
1775 WERROR result;
1776 struct spoolss_SetPrinterInfoCtr info_ctr;
1777 struct spoolss_SetPrinterInfo2 info2;
1778
1779 /* parse the command arguments */
1780 if (argc != 5)
1781 {
1782 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1783 return WERR_OK;
1784 }
1785
1786 /* Fill in the DRIVER_INFO_2 struct */
1787 ZERO_STRUCT(info2);
1788
1789 info2.printername = argv[1];
1790 info2.drivername = argv[3];
1791 info2.sharename = argv[2];
1792 info2.portname = argv[4];
1793 info2.comment = "Created by rpcclient";
1794 info2.printprocessor = "winprint";
1795 info2.datatype = "RAW";
1796 info2.devmode_ptr = 0;
1797 info2.secdesc_ptr = 0;
1798 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1799 info2.priority = 0;
1800 info2.defaultpriority = 0;
1801 info2.starttime = 0;
1802 info2.untiltime = 0;
1803
1804 /* These three fields must not be used by AddPrinter()
1805 as defined in the MS Platform SDK documentation..
1806 --jerry
1807 info2.status = 0;
1808 info2.cjobs = 0;
1809 info2.averageppm = 0;
1810 */
1811
1812 info_ctr.level = 2;
1813 info_ctr.info.info2 = &info2;
1814
1815 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1816 &info_ctr);
1817 if (W_ERROR_IS_OK(result))
1818 printf ("Printer %s successfully installed.\n", argv[1]);
1819
1820 return result;
1821}
1822
1823/****************************************************************************
1824****************************************************************************/
1825
1826static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1827 TALLOC_CTX *mem_ctx,
1828 int argc, const char **argv)
1829{
1830 struct policy_handle pol;
1831 WERROR result;
1832 NTSTATUS status;
1833 uint32_t level = 2;
1834 const char *printername;
1835 union spoolss_PrinterInfo info;
1836 struct spoolss_SetPrinterInfoCtr info_ctr;
1837 struct spoolss_SetPrinterInfo2 info2;
1838 struct spoolss_DevmodeContainer devmode_ctr;
1839 struct sec_desc_buf secdesc_ctr;
1840 struct dcerpc_binding_handle *b = cli->binding_handle;
1841
1842 ZERO_STRUCT(devmode_ctr);
1843 ZERO_STRUCT(secdesc_ctr);
1844
1845 /* parse the command arguments */
1846 if (argc != 3)
1847 {
1848 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1849 return WERR_OK;
1850 }
1851
1852 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1853
1854 /* Get a printer handle */
1855
1856 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1857 printername,
1858 PRINTER_ALL_ACCESS,
1859 &pol);
1860 if (!W_ERROR_IS_OK(result))
1861 goto done;
1862
1863 /* Get printer info */
1864
1865 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1866 &pol,
1867 level,
1868 0,
1869 &info);
1870 if (!W_ERROR_IS_OK(result)) {
1871 printf ("Unable to retrieve printer information!\n");
1872 goto done;
1873 }
1874
1875 /* Set the printer driver */
1876
1877 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1878 info2.drivername = argv[2];
1879
1880 info_ctr.level = 2;
1881 info_ctr.info.info2 = &info2;
1882
1883 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1884 &pol,
1885 &info_ctr,
1886 &devmode_ctr,
1887 &secdesc_ctr,
1888 0, /* command */
1889 &result);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 result = ntstatus_to_werror(status);
1892 goto done;
1893 }
1894 if (!W_ERROR_IS_OK(result)) {
1895 printf("SetPrinter call failed!\n");
1896 goto done;
1897 }
1898
1899 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1900
1901done:
1902 /* Cleanup */
1903
1904 if (is_valid_policy_hnd(&pol)) {
1905 WERROR _result;
1906 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1907 }
1908
1909 return result;
1910}
1911
1912
1913/****************************************************************************
1914****************************************************************************/
1915
1916static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1917 TALLOC_CTX *mem_ctx,
1918 int argc, const char **argv)
1919{
1920 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1921 NTSTATUS status;
1922 struct dcerpc_binding_handle *b = cli->binding_handle;
1923
1924 int i;
1925 int vers = -1;
1926
1927 const char *arch = NULL;
1928 uint32_t delete_flags = 0;
1929
1930 /* parse the command arguments */
1931 if (argc < 2 || argc > 4) {
1932 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1933 return WERR_OK;
1934 }
1935
1936 if (argc >= 3)
1937 arch = argv[2];
1938 if (argc == 4)
1939 vers = atoi (argv[3]);
1940
1941 if (vers >= 0) {
1942 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1943 }
1944
1945 /* delete the driver for all architectures */
1946 for (i=0; archi_table[i].long_archi; i++) {
1947
1948 if (arch && !strequal( archi_table[i].long_archi, arch))
1949 continue;
1950
1951 if (vers >= 0 && archi_table[i].version != vers)
1952 continue;
1953
1954 /* make the call to remove the driver */
1955 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1956 cli->srv_name_slash,
1957 archi_table[i].long_archi,
1958 argv[1],
1959 delete_flags,
1960 archi_table[i].version,
1961 &result);
1962 if (!NT_STATUS_IS_OK(status)) {
1963 return ntstatus_to_werror(status);
1964 }
1965 if ( !W_ERROR_IS_OK(result) )
1966 {
1967 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1968 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1969 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1970 }
1971 }
1972 else
1973 {
1974 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1975 archi_table[i].long_archi, archi_table[i].version);
1976 ret = WERR_OK;
1977 }
1978 }
1979
1980 return ret;
1981}
1982
1983
1984/****************************************************************************
1985****************************************************************************/
1986
1987static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1988 TALLOC_CTX *mem_ctx,
1989 int argc, const char **argv)
1990{
1991 WERROR result = WERR_OK;
1992 NTSTATUS status;
1993 int i;
1994 struct dcerpc_binding_handle *b = cli->binding_handle;
1995
1996 /* parse the command arguments */
1997 if (argc != 2) {
1998 printf ("Usage: %s <driver>\n", argv[0]);
1999 return WERR_OK;
2000 }
2001
2002 /* delete the driver for all architectures */
2003 for (i=0; archi_table[i].long_archi; i++) {
2004 result = WERR_OK;
2005
2006 /* make the call to remove the driver */
2007 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2008 cli->srv_name_slash,
2009 archi_table[i].long_archi,
2010 argv[1],
2011 &result);
2012 if (!NT_STATUS_IS_OK(status)) {
2013 result = ntstatus_to_werror(status);
2014 continue;
2015 }
2016 if ( !W_ERROR_IS_OK(result) ) {
2017 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2018 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2019 argv[1], archi_table[i].long_archi,
2020 win_errstr(result));
2021 }
2022 } else {
2023 printf ("Driver %s removed for arch [%s].\n", argv[1],
2024 archi_table[i].long_archi);
2025 }
2026 }
2027
2028 return result;
2029}
2030
2031/****************************************************************************
2032****************************************************************************/
2033
2034static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2035 TALLOC_CTX *mem_ctx,
2036 int argc, const char **argv)
2037{
2038 WERROR result;
2039 NTSTATUS status;
2040 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2041 DATA_BLOB buffer;
2042 uint32_t offered;
2043 union spoolss_PrintProcessorDirectoryInfo info;
2044 uint32_t needed;
2045 struct dcerpc_binding_handle *b = cli->binding_handle;
2046
2047 /* parse the command arguments */
2048 if (argc > 2) {
2049 printf ("Usage: %s [environment]\n", argv[0]);
2050 return WERR_OK;
2051 }
2052
2053 if (argc == 2) {
2054 environment = argv[1];
2055 }
2056
2057 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2058 cli->srv_name_slash,
2059 environment,
2060 1,
2061 NULL, /* buffer */
2062 0, /* offered */
2063 NULL, /* info */
2064 &needed,
2065 &result);
2066 if (!NT_STATUS_IS_OK(status)) {
2067 return ntstatus_to_werror(status);
2068 }
2069 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2070 offered = needed;
2071 buffer = data_blob_talloc_zero(mem_ctx, needed);
2072
2073 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2074 cli->srv_name_slash,
2075 environment,
2076 1,
2077 &buffer,
2078 offered,
2079 &info,
2080 &needed,
2081 &result);
2082 if (!NT_STATUS_IS_OK(status)) {
2083 return ntstatus_to_werror(status);
2084 }
2085 }
2086
2087 if (W_ERROR_IS_OK(result)) {
2088 printf("%s\n", info.info1.directory_name);
2089 }
2090
2091 return result;
2092}
2093
2094/****************************************************************************
2095****************************************************************************/
2096
2097static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2098 int argc, const char **argv)
2099{
2100 struct policy_handle handle;
2101 WERROR werror;
2102 NTSTATUS status;
2103 const char *printername;
2104 union spoolss_AddFormInfo info;
2105 struct spoolss_AddFormInfo1 info1;
2106 struct spoolss_AddFormInfo2 info2;
2107 uint32_t level = 1;
2108 struct dcerpc_binding_handle *b = cli->binding_handle;
2109
2110 /* Parse the command arguments */
2111
2112 if (argc < 3 || argc > 5) {
2113 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2114 return WERR_OK;
2115 }
2116
2117 /* Get a printer handle */
2118
2119 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2120
2121 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2122 printername,
2123 PRINTER_ALL_ACCESS,
2124 &handle);
2125 if (!W_ERROR_IS_OK(werror))
2126 goto done;
2127
2128 /* Dummy up some values for the form data */
2129
2130 if (argc == 4) {
2131 level = atoi(argv[3]);
2132 }
2133
2134 switch (level) {
2135 case 1:
2136 info1.flags = SPOOLSS_FORM_USER;
2137 info1.form_name = argv[2];
2138 info1.size.width = 100;
2139 info1.size.height = 100;
2140 info1.area.left = 0;
2141 info1.area.top = 10;
2142 info1.area.right = 20;
2143 info1.area.bottom = 30;
2144
2145 info.info1 = &info1;
2146
2147 break;
2148 case 2:
2149 info2.flags = SPOOLSS_FORM_USER;
2150 info2.form_name = argv[2];
2151 info2.size.width = 100;
2152 info2.size.height = 100;
2153 info2.area.left = 0;
2154 info2.area.top = 10;
2155 info2.area.right = 20;
2156 info2.area.bottom = 30;
2157 info2.keyword = argv[2];
2158 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2159 info2.mui_dll = NULL;
2160 info2.ressource_id = 0;
2161 info2.display_name = argv[2];
2162 info2.lang_id = 0;
2163
2164 info.info2 = &info2;
2165
2166 break;
2167 default:
2168 werror = WERR_INVALID_PARAM;
2169 goto done;
2170 }
2171
2172 /* Add the form */
2173
2174
2175 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2176 &handle,
2177 level,
2178 info,
2179 &werror);
2180 if (!NT_STATUS_IS_OK(status)) {
2181 werror = ntstatus_to_werror(status);
2182 goto done;
2183 }
2184 done:
2185 if (is_valid_policy_hnd(&handle)) {
2186 WERROR _result;
2187 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2188 }
2189
2190 return werror;
2191}
2192
2193/****************************************************************************
2194****************************************************************************/
2195
2196static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2197 int argc, const char **argv)
2198{
2199 struct policy_handle handle;
2200 WERROR werror;
2201 NTSTATUS status;
2202 const char *printername;
2203 union spoolss_AddFormInfo info;
2204 struct spoolss_AddFormInfo1 info1;
2205 struct dcerpc_binding_handle *b = cli->binding_handle;
2206
2207 /* Parse the command arguments */
2208
2209 if (argc != 3) {
2210 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2211 return WERR_OK;
2212 }
2213
2214 /* Get a printer handle */
2215
2216 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2217
2218 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2219 printername,
2220 SEC_FLAG_MAXIMUM_ALLOWED,
2221 &handle);
2222 if (!W_ERROR_IS_OK(werror))
2223 goto done;
2224
2225 /* Dummy up some values for the form data */
2226
2227 info1.flags = SPOOLSS_FORM_PRINTER;
2228 info1.size.width = 100;
2229 info1.size.height = 100;
2230 info1.area.left = 0;
2231 info1.area.top = 1000;
2232 info1.area.right = 2000;
2233 info1.area.bottom = 3000;
2234 info1.form_name = argv[2];
2235
2236 info.info1 = &info1;
2237
2238 /* Set the form */
2239
2240 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2241 &handle,
2242 argv[2],
2243 1,
2244 info,
2245 &werror);
2246 if (!NT_STATUS_IS_OK(status)) {
2247 werror = ntstatus_to_werror(status);
2248 goto done;
2249 }
2250 done:
2251 if (is_valid_policy_hnd(&handle)) {
2252 WERROR _result;
2253 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2254 }
2255
2256 return werror;
2257}
2258
2259/****************************************************************************
2260****************************************************************************/
2261
2262static const char *get_form_flag(int form_flag)
2263{
2264 switch (form_flag) {
2265 case SPOOLSS_FORM_USER:
2266 return "FORM_USER";
2267 case SPOOLSS_FORM_BUILTIN:
2268 return "FORM_BUILTIN";
2269 case SPOOLSS_FORM_PRINTER:
2270 return "FORM_PRINTER";
2271 default:
2272 return "unknown";
2273 }
2274}
2275
2276/****************************************************************************
2277****************************************************************************/
2278
2279static void display_form_info1(struct spoolss_FormInfo1 *r)
2280{
2281 printf("%s\n" \
2282 "\tflag: %s (%d)\n" \
2283 "\twidth: %d, length: %d\n" \
2284 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2285 r->form_name, get_form_flag(r->flags), r->flags,
2286 r->size.width, r->size.height,
2287 r->area.left, r->area.right,
2288 r->area.top, r->area.bottom);
2289}
2290
2291/****************************************************************************
2292****************************************************************************/
2293
2294static void display_form_info2(struct spoolss_FormInfo2 *r)
2295{
2296 printf("%s\n" \
2297 "\tflag: %s (%d)\n" \
2298 "\twidth: %d, length: %d\n" \
2299 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2300 r->form_name, get_form_flag(r->flags), r->flags,
2301 r->size.width, r->size.height,
2302 r->area.left, r->area.right,
2303 r->area.top, r->area.bottom);
2304 printf("\tkeyword: %s\n", r->keyword);
2305 printf("\tstring_type: 0x%08x\n", r->string_type);
2306 printf("\tmui_dll: %s\n", r->mui_dll);
2307 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2308 printf("\tdisplay_name: %s\n", r->display_name);
2309 printf("\tlang_id: %d\n", r->lang_id);
2310 printf("\n");
2311}
2312
2313/****************************************************************************
2314****************************************************************************/
2315
2316static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2317 int argc, const char **argv)
2318{
2319 struct policy_handle handle;
2320 WERROR werror;
2321 NTSTATUS status;
2322 const char *printername;
2323 DATA_BLOB buffer;
2324 uint32_t offered = 0;
2325 union spoolss_FormInfo info;
2326 uint32_t needed;
2327 uint32_t level = 1;
2328 struct dcerpc_binding_handle *b = cli->binding_handle;
2329
2330 /* Parse the command arguments */
2331
2332 if (argc < 3 || argc > 5) {
2333 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2334 return WERR_OK;
2335 }
2336
2337 /* Get a printer handle */
2338
2339 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2340
2341 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2342 printername,
2343 SEC_FLAG_MAXIMUM_ALLOWED,
2344 &handle);
2345 if (!W_ERROR_IS_OK(werror))
2346 goto done;
2347
2348 if (argc == 4) {
2349 level = atoi(argv[3]);
2350 }
2351
2352 /* Get the form */
2353
2354 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2355 &handle,
2356 argv[2],
2357 level,
2358 NULL,
2359 offered,
2360 &info,
2361 &needed,
2362 &werror);
2363 if (!NT_STATUS_IS_OK(status)) {
2364 werror = ntstatus_to_werror(status);
2365 goto done;
2366 }
2367 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2368 buffer = data_blob_talloc_zero(mem_ctx, needed);
2369 offered = needed;
2370 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2371 &handle,
2372 argv[2],
2373 level,
2374 &buffer,
2375 offered,
2376 &info,
2377 &needed,
2378 &werror);
2379 if (!NT_STATUS_IS_OK(status)) {
2380 werror = ntstatus_to_werror(status);
2381 goto done;
2382 }
2383 }
2384
2385 if (!W_ERROR_IS_OK(werror)) {
2386 goto done;
2387 }
2388
2389 switch (level) {
2390 case 1:
2391 display_form_info1(&info.info1);
2392 break;
2393 case 2:
2394 display_form_info2(&info.info2);
2395 break;
2396 }
2397
2398 done:
2399 if (is_valid_policy_hnd(&handle)) {
2400 WERROR _result;
2401 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2402 }
2403
2404 return werror;
2405}
2406
2407/****************************************************************************
2408****************************************************************************/
2409
2410static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2411 TALLOC_CTX *mem_ctx, int argc,
2412 const char **argv)
2413{
2414 struct policy_handle handle;
2415 WERROR werror;
2416 NTSTATUS status;
2417 const char *printername;
2418 struct dcerpc_binding_handle *b = cli->binding_handle;
2419
2420 /* Parse the command arguments */
2421
2422 if (argc != 3) {
2423 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2424 return WERR_OK;
2425 }
2426
2427 /* Get a printer handle */
2428
2429 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2430
2431 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2432 printername,
2433 SEC_FLAG_MAXIMUM_ALLOWED,
2434 &handle);
2435 if (!W_ERROR_IS_OK(werror))
2436 goto done;
2437
2438 /* Delete the form */
2439
2440 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2441 &handle,
2442 argv[2],
2443 &werror);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 werror = ntstatus_to_werror(status);
2446 goto done;
2447 }
2448
2449 done:
2450 if (is_valid_policy_hnd(&handle)) {
2451 WERROR _result;
2452 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2453 }
2454
2455 return werror;
2456}
2457
2458/****************************************************************************
2459****************************************************************************/
2460
2461static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2462 TALLOC_CTX *mem_ctx, int argc,
2463 const char **argv)
2464{
2465 struct policy_handle handle;
2466 WERROR werror;
2467 const char *printername;
2468 uint32_t num_forms, level = 1, i;
2469 union spoolss_FormInfo *forms;
2470 struct dcerpc_binding_handle *b = cli->binding_handle;
2471
2472 /* Parse the command arguments */
2473
2474 if (argc < 2 || argc > 4) {
2475 printf ("Usage: %s <printer> [level]\n", argv[0]);
2476 return WERR_OK;
2477 }
2478
2479 /* Get a printer handle */
2480
2481 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2482
2483 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2484 printername,
2485 SEC_FLAG_MAXIMUM_ALLOWED,
2486 &handle);
2487 if (!W_ERROR_IS_OK(werror))
2488 goto done;
2489
2490 if (argc == 3) {
2491 level = atoi(argv[2]);
2492 }
2493
2494 /* Enumerate forms */
2495
2496 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2497 &handle,
2498 level,
2499 0,
2500 &num_forms,
2501 &forms);
2502
2503 if (!W_ERROR_IS_OK(werror))
2504 goto done;
2505
2506 /* Display output */
2507
2508 for (i = 0; i < num_forms; i++) {
2509 switch (level) {
2510 case 1:
2511 display_form_info1(&forms[i].info1);
2512 break;
2513 case 2:
2514 display_form_info2(&forms[i].info2);
2515 break;
2516 }
2517 }
2518
2519 done:
2520 if (is_valid_policy_hnd(&handle)) {
2521 WERROR _result;
2522 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2523 }
2524
2525 return werror;
2526}
2527
2528/****************************************************************************
2529****************************************************************************/
2530
2531static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2532 TALLOC_CTX *mem_ctx,
2533 int argc, const char **argv)
2534{
2535 WERROR result;
2536 NTSTATUS status;
2537 const char *printername;
2538 struct policy_handle pol;
2539 union spoolss_PrinterInfo info;
2540 enum winreg_Type type;
2541 union spoolss_PrinterData data;
2542 DATA_BLOB blob;
2543 struct dcerpc_binding_handle *b = cli->binding_handle;
2544
2545 /* parse the command arguments */
2546 if (argc < 5) {
2547 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2548 " <value> <data>\n",
2549 argv[0]);
2550 return WERR_OK;
2551 }
2552
2553 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2554
2555 type = REG_NONE;
2556
2557 if (strequal(argv[2], "string")) {
2558 type = REG_SZ;
2559 }
2560
2561 if (strequal(argv[2], "binary")) {
2562 type = REG_BINARY;
2563 }
2564
2565 if (strequal(argv[2], "dword")) {
2566 type = REG_DWORD;
2567 }
2568
2569 if (strequal(argv[2], "multistring")) {
2570 type = REG_MULTI_SZ;
2571 }
2572
2573 if (type == REG_NONE) {
2574 printf("Unknown data type: %s\n", argv[2]);
2575 result = WERR_INVALID_PARAM;
2576 goto done;
2577 }
2578
2579 /* get a printer handle */
2580
2581 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2582 printername,
2583 SEC_FLAG_MAXIMUM_ALLOWED,
2584 &pol);
2585 if (!W_ERROR_IS_OK(result)) {
2586 goto done;
2587 }
2588
2589 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2590 &pol,
2591 0,
2592 0,
2593 &info);
2594 if (!W_ERROR_IS_OK(result)) {
2595 goto done;
2596 }
2597
2598 printf("%s\n", current_timestring(mem_ctx, true));
2599 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2600
2601 /* Set the printer data */
2602
2603 switch (type) {
2604 case REG_SZ:
2605 data.string = talloc_strdup(mem_ctx, argv[4]);
2606 W_ERROR_HAVE_NO_MEMORY(data.string);
2607 break;
2608 case REG_DWORD:
2609 data.value = strtoul(argv[4], NULL, 10);
2610 break;
2611 case REG_BINARY:
2612 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2613 break;
2614 case REG_MULTI_SZ: {
2615 int i, num_strings;
2616 const char **strings = NULL;
2617
2618 for (i=4; i<argc; i++) {
2619 if (strcmp(argv[i], "NULL") == 0) {
2620 argv[i] = "";
2621 }
2622 if (!add_string_to_array(mem_ctx, argv[i],
2623 &strings,
2624 &num_strings)) {
2625 result = WERR_NOMEM;
2626 goto done;
2627 }
2628 }
2629 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2630 if (!data.string_array) {
2631 result = WERR_NOMEM;
2632 goto done;
2633 }
2634 for (i=0; i < num_strings; i++) {
2635 data.string_array[i] = strings[i];
2636 }
2637 break;
2638 }
2639 default:
2640 printf("Unknown data type: %s\n", argv[2]);
2641 result = WERR_INVALID_PARAM;
2642 goto done;
2643 }
2644
2645 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2646 if (!W_ERROR_IS_OK(result)) {
2647 goto done;
2648 }
2649
2650 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2651 &pol,
2652 argv[3], /* value_name */
2653 type,
2654 blob.data,
2655 blob.length,
2656 &result);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2659 result = ntstatus_to_werror(status);
2660 goto done;
2661 }
2662 if (!W_ERROR_IS_OK(result)) {
2663 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2664 goto done;
2665 }
2666 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2667
2668 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2669 &pol,
2670 0,
2671 0,
2672 &info);
2673 if (!W_ERROR_IS_OK(result)) {
2674 goto done;
2675 }
2676
2677 printf("%s\n", current_timestring(mem_ctx, true));
2678 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2679
2680done:
2681 /* cleanup */
2682 if (is_valid_policy_hnd(&pol)) {
2683 WERROR _result;
2684 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2685 }
2686
2687 return result;
2688}
2689
2690/****************************************************************************
2691****************************************************************************/
2692
2693static void display_job_info1(struct spoolss_JobInfo1 *r)
2694{
2695 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2696 r->user_name, r->document_name, r->text_status, r->pages_printed,
2697 r->total_pages);
2698}
2699
2700/****************************************************************************
2701****************************************************************************/
2702
2703static void display_job_info2(struct spoolss_JobInfo2 *r)
2704{
2705 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2706 r->position, r->job_id,
2707 r->user_name, r->document_name, r->text_status, r->pages_printed,
2708 r->total_pages, r->size);
2709}
2710
2711/****************************************************************************
2712****************************************************************************/
2713
2714static void display_job_info3(struct spoolss_JobInfo3 *r)
2715{
2716 printf("jobid[%d], next_jobid[%d]\n",
2717 r->job_id, r->next_job_id);
2718}
2719
2720/****************************************************************************
2721****************************************************************************/
2722
2723static void display_job_info4(struct spoolss_JobInfo4 *r)
2724{
2725 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2726 r->position, r->job_id,
2727 r->user_name, r->document_name, r->text_status, r->pages_printed,
2728 r->total_pages, r->size, r->size_high);
2729}
2730
2731/****************************************************************************
2732****************************************************************************/
2733
2734static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2735 TALLOC_CTX *mem_ctx, int argc,
2736 const char **argv)
2737{
2738 WERROR result;
2739 uint32_t level = 1, count, i;
2740 const char *printername;
2741 struct policy_handle hnd;
2742 union spoolss_JobInfo *info;
2743 struct dcerpc_binding_handle *b = cli->binding_handle;
2744
2745 if (argc < 2 || argc > 3) {
2746 printf("Usage: %s printername [level]\n", argv[0]);
2747 return WERR_OK;
2748 }
2749
2750 if (argc == 3) {
2751 level = atoi(argv[2]);
2752 }
2753
2754 /* Open printer handle */
2755
2756 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2757
2758 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2759 printername,
2760 SEC_FLAG_MAXIMUM_ALLOWED,
2761 &hnd);
2762 if (!W_ERROR_IS_OK(result))
2763 goto done;
2764
2765 /* Enumerate ports */
2766
2767 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2768 &hnd,
2769 0, /* firstjob */
2770 1000, /* numjobs */
2771 level,
2772 0,
2773 &count,
2774 &info);
2775 if (!W_ERROR_IS_OK(result)) {
2776 goto done;
2777 }
2778
2779 for (i = 0; i < count; i++) {
2780 switch (level) {
2781 case 1:
2782 display_job_info1(&info[i].info1);
2783 break;
2784 case 2:
2785 display_job_info2(&info[i].info2);
2786 break;
2787 default:
2788 d_printf("unknown info level %d\n", level);
2789 break;
2790 }
2791 }
2792
2793done:
2794 if (is_valid_policy_hnd(&hnd)) {
2795 WERROR _result;
2796 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2797 }
2798
2799 return result;
2800}
2801
2802/****************************************************************************
2803****************************************************************************/
2804
2805static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2806 TALLOC_CTX *mem_ctx, int argc,
2807 const char **argv)
2808{
2809 WERROR result;
2810 const char *printername;
2811 struct policy_handle hnd;
2812 uint32_t job_id;
2813 uint32_t level = 1;
2814 union spoolss_JobInfo info;
2815 struct dcerpc_binding_handle *b = cli->binding_handle;
2816
2817 if (argc < 3 || argc > 4) {
2818 printf("Usage: %s printername job_id [level]\n", argv[0]);
2819 return WERR_OK;
2820 }
2821
2822 job_id = atoi(argv[2]);
2823
2824 if (argc == 4) {
2825 level = atoi(argv[3]);
2826 }
2827
2828 /* Open printer handle */
2829
2830 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2831
2832 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2833 printername,
2834 SEC_FLAG_MAXIMUM_ALLOWED,
2835 &hnd);
2836 if (!W_ERROR_IS_OK(result)) {
2837 goto done;
2838 }
2839
2840 /* Enumerate ports */
2841
2842 result = rpccli_spoolss_getjob(cli, mem_ctx,
2843 &hnd,
2844 job_id,
2845 level,
2846 0,
2847 &info);
2848
2849 if (!W_ERROR_IS_OK(result)) {
2850 goto done;
2851 }
2852
2853 switch (level) {
2854 case 1:
2855 display_job_info1(&info.info1);
2856 break;
2857 case 2:
2858 display_job_info2(&info.info2);
2859 break;
2860 case 3:
2861 display_job_info3(&info.info3);
2862 break;
2863 case 4:
2864 display_job_info4(&info.info4);
2865 break;
2866 default:
2867 d_printf("unknown info level %d\n", level);
2868 break;
2869 }
2870
2871done:
2872 if (is_valid_policy_hnd(&hnd)) {
2873 WERROR _result;
2874 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2875 }
2876
2877 return result;
2878}
2879
2880/****************************************************************************
2881****************************************************************************/
2882
2883static struct {
2884 const char *name;
2885 enum spoolss_JobControl val;
2886} cmdvals[] = {
2887 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2888 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2889 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2890 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2891 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2892 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2893 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2894 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2895 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2896};
2897
2898static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2899{
2900 int i;
2901
2902 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2903 if (strequal(cmdvals[i].name, cmd)) {
2904 return cmdvals[i].val;
2905 }
2906 }
2907 return (enum spoolss_JobControl)atoi(cmd);
2908}
2909
2910static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2911 TALLOC_CTX *mem_ctx, int argc,
2912 const char **argv)
2913{
2914 WERROR result;
2915 NTSTATUS status;
2916 const char *printername;
2917 struct policy_handle hnd;
2918 uint32_t job_id;
2919 enum spoolss_JobControl command;
2920 struct dcerpc_binding_handle *b = cli->binding_handle;
2921
2922 if (argc != 4) {
2923 printf("Usage: %s printername job_id command\n", argv[0]);
2924 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2925 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2926 return WERR_OK;
2927 }
2928
2929 job_id = atoi(argv[2]);
2930 command = parse_setjob_command(argv[3]);
2931
2932 /* Open printer handle */
2933
2934 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2935
2936 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2937 printername,
2938 SEC_FLAG_MAXIMUM_ALLOWED,
2939 &hnd);
2940 if (!W_ERROR_IS_OK(result)) {
2941 goto done;
2942 }
2943
2944 /* Set Job */
2945
2946 status = dcerpc_spoolss_SetJob(b, mem_ctx,
2947 &hnd,
2948 job_id,
2949 NULL,
2950 command,
2951 &result);
2952 if (!NT_STATUS_IS_OK(status)) {
2953 result = ntstatus_to_werror(status);
2954 goto done;
2955 }
2956 if (!W_ERROR_IS_OK(result)) {
2957 goto done;
2958 }
2959
2960done:
2961 if (is_valid_policy_hnd(&hnd)) {
2962 WERROR _result;
2963 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2964 }
2965
2966 return result;
2967}
2968
2969/****************************************************************************
2970****************************************************************************/
2971
2972static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2973 TALLOC_CTX *mem_ctx, int argc,
2974 const char **argv)
2975{
2976 WERROR result;
2977 NTSTATUS status;
2978 const char *printername;
2979 struct policy_handle hnd;
2980 uint32_t value_needed;
2981 enum winreg_Type type;
2982 uint32_t data_needed;
2983 struct dcerpc_binding_handle *b = cli->binding_handle;
2984 struct spoolss_EnumPrinterData r;
2985
2986 if (argc != 2) {
2987 printf("Usage: %s printername\n", argv[0]);
2988 return WERR_OK;
2989 }
2990
2991 /* Open printer handle */
2992
2993 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2994
2995 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2996 printername,
2997 SEC_FLAG_MAXIMUM_ALLOWED,
2998 &hnd);
2999 if (!W_ERROR_IS_OK(result)) {
3000 goto done;
3001 }
3002
3003 /* Enumerate data */
3004
3005 r.in.handle = &hnd;
3006 r.in.enum_index = 0;
3007 r.in.value_offered = 0;
3008 r.in.data_offered = 0;
3009 r.out.value_name = NULL;
3010 r.out.value_needed = &value_needed;
3011 r.out.type = &type;
3012 r.out.data = NULL;
3013 r.out.data_needed = &data_needed;
3014
3015 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3016 if (!NT_STATUS_IS_OK(status)) {
3017 result = ntstatus_to_werror(status);
3018 goto done;
3019 }
3020
3021 if (!W_ERROR_IS_OK(r.out.result)) {
3022 result = r.out.result;
3023 goto done;
3024 }
3025
3026 r.in.data_offered = *r.out.data_needed;
3027 r.in.value_offered = *r.out.value_needed;
3028 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3029 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3030
3031 do {
3032
3033 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3034 if (!NT_STATUS_IS_OK(status)) {
3035 result = ntstatus_to_werror(status);
3036 goto done;
3037 }
3038
3039 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3040 result = WERR_OK;
3041 break;
3042 }
3043
3044 r.in.enum_index++;
3045
3046 {
3047 struct regval_blob *v;
3048
3049 v = regval_compose(talloc_tos(),
3050 r.out.value_name,
3051 *r.out.type,
3052 r.out.data,
3053 r.in.data_offered);
3054 if (v == NULL) {
3055 result = WERR_NOMEM;
3056 goto done;
3057 }
3058
3059 display_reg_value(v);
3060 talloc_free(v);
3061 }
3062
3063 } while (W_ERROR_IS_OK(r.out.result));
3064
3065done:
3066 if (is_valid_policy_hnd(&hnd)) {
3067 WERROR _result;
3068 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3069 }
3070
3071 return result;
3072}
3073
3074/****************************************************************************
3075****************************************************************************/
3076
3077static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3078 TALLOC_CTX *mem_ctx, int argc,
3079 const char **argv)
3080{
3081 WERROR result;
3082 uint32_t i;
3083 const char *printername;
3084 struct policy_handle hnd;
3085 uint32_t count;
3086 struct spoolss_PrinterEnumValues *info;
3087 struct dcerpc_binding_handle *b = cli->binding_handle;
3088
3089 if (argc != 3) {
3090 printf("Usage: %s printername <keyname>\n", argv[0]);
3091 return WERR_OK;
3092 }
3093
3094 /* Open printer handle */
3095
3096 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3097
3098 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3099 printername,
3100 SEC_FLAG_MAXIMUM_ALLOWED,
3101 &hnd);
3102 if (!W_ERROR_IS_OK(result)) {
3103 goto done;
3104 }
3105
3106 /* Enumerate subkeys */
3107
3108 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3109 &hnd,
3110 argv[2],
3111 0,
3112 &count,
3113 &info);
3114 if (!W_ERROR_IS_OK(result)) {
3115 goto done;
3116 }
3117
3118 for (i=0; i < count; i++) {
3119 display_printer_data(info[i].value_name,
3120 info[i].type,
3121 info[i].data->data,
3122 info[i].data->length);
3123 }
3124
3125 done:
3126 if (is_valid_policy_hnd(&hnd)) {
3127 WERROR _result;
3128 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3129 }
3130
3131 return result;
3132}
3133
3134/****************************************************************************
3135****************************************************************************/
3136
3137static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3138 TALLOC_CTX *mem_ctx, int argc,
3139 const char **argv)
3140{
3141 WERROR result;
3142 const char *printername;
3143 const char *keyname = NULL;
3144 struct policy_handle hnd;
3145 const char **key_buffer = NULL;
3146 int i;
3147 uint32_t offered = 0;
3148 struct dcerpc_binding_handle *b = cli->binding_handle;
3149
3150 if (argc < 2 || argc > 4) {
3151 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3152 return WERR_OK;
3153 }
3154
3155 if (argc >= 3) {
3156 keyname = argv[2];
3157 } else {
3158 keyname = "";
3159 }
3160
3161 if (argc == 4) {
3162 offered = atoi(argv[3]);
3163 }
3164
3165 /* Open printer handle */
3166
3167 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3168
3169 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3170 printername,
3171 SEC_FLAG_MAXIMUM_ALLOWED,
3172 &hnd);
3173 if (!W_ERROR_IS_OK(result)) {
3174 goto done;
3175 }
3176
3177 /* Enumerate subkeys */
3178
3179 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3180 &hnd,
3181 keyname,
3182 &key_buffer,
3183 offered);
3184
3185 if (!W_ERROR_IS_OK(result)) {
3186 goto done;
3187 }
3188
3189 for (i=0; key_buffer && key_buffer[i]; i++) {
3190 printf("%s\n", key_buffer[i]);
3191 }
3192
3193 done:
3194
3195 if (is_valid_policy_hnd(&hnd)) {
3196 WERROR _result;
3197 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3198 }
3199
3200 return result;
3201}
3202
3203/****************************************************************************
3204****************************************************************************/
3205
3206static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3207 TALLOC_CTX *mem_ctx, int argc,
3208 const char **argv)
3209{
3210 const char *printername;
3211 const char *clientname;
3212 struct policy_handle hnd;
3213 WERROR result;
3214 NTSTATUS status;
3215 struct spoolss_NotifyOption option;
3216 struct dcerpc_binding_handle *b = cli->binding_handle;
3217
3218 if (argc != 2) {
3219 printf("Usage: %s printername\n", argv[0]);
3220 result = WERR_OK;
3221 goto done;
3222 }
3223
3224 /* Open printer */
3225
3226 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3227
3228 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3229 printername,
3230 SEC_FLAG_MAXIMUM_ALLOWED,
3231 &hnd);
3232 if (!W_ERROR_IS_OK(result)) {
3233 printf("Error opening %s\n", argv[1]);
3234 goto done;
3235 }
3236
3237 /* Create spool options */
3238
3239 option.version = 2;
3240 option.count = 2;
3241
3242 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3243 if (option.types == NULL) {
3244 result = WERR_NOMEM;
3245 goto done;
3246 }
3247
3248 option.types[0].type = PRINTER_NOTIFY_TYPE;
3249 option.types[0].count = 1;
3250 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3251 if (option.types[0].fields == NULL) {
3252 result = WERR_NOMEM;
3253 goto done;
3254 }
3255 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3256
3257 option.types[1].type = JOB_NOTIFY_TYPE;
3258 option.types[1].count = 1;
3259 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3260 if (option.types[1].fields == NULL) {
3261 result = WERR_NOMEM;
3262 goto done;
3263 }
3264 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3265
3266 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3267 if (!clientname) {
3268 result = WERR_NOMEM;
3269 goto done;
3270 }
3271
3272 /* Send rffpcnex */
3273
3274 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3275 &hnd,
3276 0,
3277 0,
3278 clientname,
3279 123,
3280 &option,
3281 &result);
3282 if (!NT_STATUS_IS_OK(status)) {
3283 result = ntstatus_to_werror(status);
3284 goto done;
3285 }
3286 if (!W_ERROR_IS_OK(result)) {
3287 printf("Error rffpcnex %s\n", argv[1]);
3288 goto done;
3289 }
3290
3291done:
3292 if (is_valid_policy_hnd(&hnd)) {
3293 WERROR _result;
3294 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3295 }
3296
3297 return result;
3298}
3299
3300/****************************************************************************
3301****************************************************************************/
3302
3303static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3304 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3305{
3306 union spoolss_PrinterInfo info1, info2;
3307 WERROR werror;
3308 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3309
3310 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3311 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3312 hnd1,
3313 2,
3314 0,
3315 &info1);
3316 if ( !W_ERROR_IS_OK(werror) ) {
3317 printf("failed (%s)\n", win_errstr(werror));
3318 talloc_destroy(mem_ctx);
3319 return false;
3320 }
3321 printf("ok\n");
3322
3323 printf("Retrieving printer properties for %s...", cli2->desthost);
3324 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3325 hnd2,
3326 2,
3327 0,
3328 &info2);
3329 if ( !W_ERROR_IS_OK(werror) ) {
3330 printf("failed (%s)\n", win_errstr(werror));
3331 talloc_destroy(mem_ctx);
3332 return false;
3333 }
3334 printf("ok\n");
3335
3336 talloc_destroy(mem_ctx);
3337
3338 return true;
3339}
3340
3341/****************************************************************************
3342****************************************************************************/
3343
3344static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3345 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3346{
3347 union spoolss_PrinterInfo info1, info2;
3348 WERROR werror;
3349 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3350 struct security_descriptor *sd1, *sd2;
3351 bool result = true;
3352
3353
3354 printf("Retrieving printer security for %s...", cli1->desthost);
3355 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3356 hnd1,
3357 3,
3358 0,
3359 &info1);
3360 if ( !W_ERROR_IS_OK(werror) ) {
3361 printf("failed (%s)\n", win_errstr(werror));
3362 result = false;
3363 goto done;
3364 }
3365 printf("ok\n");
3366
3367 printf("Retrieving printer security for %s...", cli2->desthost);
3368 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3369 hnd2,
3370 3,
3371 0,
3372 &info2);
3373 if ( !W_ERROR_IS_OK(werror) ) {
3374 printf("failed (%s)\n", win_errstr(werror));
3375 result = false;
3376 goto done;
3377 }
3378 printf("ok\n");
3379
3380
3381 printf("++ ");
3382
3383 sd1 = info1.info3.secdesc;
3384 sd2 = info2.info3.secdesc;
3385
3386 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3387 printf("NULL secdesc!\n");
3388 result = false;
3389 goto done;
3390 }
3391
3392 if (!security_descriptor_equal( sd1, sd2 ) ) {
3393 printf("Security Descriptors *not* equal!\n");
3394 result = false;
3395 goto done;
3396 }
3397
3398 printf("Security descriptors match\n");
3399
3400done:
3401 talloc_destroy(mem_ctx);
3402 return result;
3403}
3404
3405
3406/****************************************************************************
3407****************************************************************************/
3408
3409extern struct user_auth_info *rpcclient_auth_info;
3410
3411static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3412 TALLOC_CTX *mem_ctx, int argc,
3413 const char **argv)
3414{
3415 const char *printername;
3416 char *printername_path = NULL;
3417 struct cli_state *cli_server2 = NULL;
3418 struct rpc_pipe_client *cli2 = NULL;
3419 struct policy_handle hPrinter1, hPrinter2;
3420 NTSTATUS nt_status;
3421 WERROR werror;
3422
3423 if ( argc != 3 ) {
3424 printf("Usage: %s <printer> <server>\n", argv[0]);
3425 return WERR_OK;
3426 }
3427
3428 printername = argv[1];
3429
3430 /* first get the connection to the remote server */
3431
3432 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3433 NULL, 0,
3434 "IPC$", "IPC",
3435 get_cmdline_auth_info_username(rpcclient_auth_info),
3436 lp_workgroup(),
3437 get_cmdline_auth_info_password(rpcclient_auth_info),
3438 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3439 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3440
3441 if ( !NT_STATUS_IS_OK(nt_status) )
3442 return WERR_GENERAL_FAILURE;
3443
3444 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3445 &cli2);
3446 if (!NT_STATUS_IS_OK(nt_status)) {
3447 printf("failed to open spoolss pipe on server %s (%s)\n",
3448 argv[2], nt_errstr(nt_status));
3449 return WERR_GENERAL_FAILURE;
3450 }
3451
3452 /* now open up both printers */
3453
3454 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3455
3456 printf("Opening %s...", printername_path);
3457
3458 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3459 printername_path,
3460 PRINTER_ALL_ACCESS,
3461 &hPrinter1);
3462 if ( !W_ERROR_IS_OK(werror) ) {
3463 printf("failed (%s)\n", win_errstr(werror));
3464 goto done;
3465 }
3466 printf("ok\n");
3467
3468 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3469
3470 printf("Opening %s...", printername_path);
3471 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3472 printername_path,
3473 PRINTER_ALL_ACCESS,
3474 &hPrinter2);
3475 if ( !W_ERROR_IS_OK(werror) ) {
3476 printf("failed (%s)\n", win_errstr(werror));
3477 goto done;
3478 }
3479 printf("ok\n");
3480
3481 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3482 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3483#if 0
3484 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3485#endif
3486
3487
3488done:
3489 /* cleanup */
3490
3491 printf("Closing printers...");
3492 {
3493 WERROR _result;
3494 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3495 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3496 }
3497 printf("ok\n");
3498
3499 /* close the second remote connection */
3500
3501 cli_shutdown( cli_server2 );
3502 return WERR_OK;
3503}
3504
3505static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3506{
3507 printf("print_processor_name: %s\n", r->print_processor_name);
3508}
3509
3510static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3511 TALLOC_CTX *mem_ctx, int argc,
3512 const char **argv)
3513{
3514 WERROR werror;
3515 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3516 uint32_t num_procs, level = 1, i;
3517 union spoolss_PrintProcessorInfo *procs;
3518
3519 /* Parse the command arguments */
3520
3521 if (argc < 1 || argc > 4) {
3522 printf ("Usage: %s [environment] [level]\n", argv[0]);
3523 return WERR_OK;
3524 }
3525
3526 if (argc >= 2) {
3527 environment = argv[1];
3528 }
3529
3530 if (argc == 3) {
3531 level = atoi(argv[2]);
3532 }
3533
3534 /* Enumerate Print Processors */
3535
3536 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3537 cli->srv_name_slash,
3538 environment,
3539 level,
3540 0,
3541 &num_procs,
3542 &procs);
3543 if (!W_ERROR_IS_OK(werror))
3544 goto done;
3545
3546 /* Display output */
3547
3548 for (i = 0; i < num_procs; i++) {
3549 switch (level) {
3550 case 1:
3551 display_proc_info1(&procs[i].info1);
3552 break;
3553 }
3554 }
3555
3556 done:
3557 return werror;
3558}
3559
3560static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3561{
3562 printf("name_array: %s\n", r->name_array);
3563}
3564
3565static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3566 TALLOC_CTX *mem_ctx, int argc,
3567 const char **argv)
3568{
3569 WERROR werror;
3570 const char *print_processor_name = "winprint";
3571 uint32_t num_procs, level = 1, i;
3572 union spoolss_PrintProcDataTypesInfo *procs;
3573
3574 /* Parse the command arguments */
3575
3576 if (argc < 1 || argc > 4) {
3577 printf ("Usage: %s [environment] [level]\n", argv[0]);
3578 return WERR_OK;
3579 }
3580
3581 if (argc >= 2) {
3582 print_processor_name = argv[1];
3583 }
3584
3585 if (argc == 3) {
3586 level = atoi(argv[2]);
3587 }
3588
3589 /* Enumerate Print Processor Data Types */
3590
3591 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3592 cli->srv_name_slash,
3593 print_processor_name,
3594 level,
3595 0,
3596 &num_procs,
3597 &procs);
3598 if (!W_ERROR_IS_OK(werror))
3599 goto done;
3600
3601 /* Display output */
3602
3603 for (i = 0; i < num_procs; i++) {
3604 switch (level) {
3605 case 1:
3606 display_proc_data_types_info1(&procs[i].info1);
3607 break;
3608 }
3609 }
3610
3611 done:
3612 return werror;
3613}
3614
3615static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3616{
3617 printf("monitor_name: %s\n", r->monitor_name);
3618}
3619
3620static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3621{
3622 printf("monitor_name: %s\n", r->monitor_name);
3623 printf("environment: %s\n", r->environment);
3624 printf("dll_name: %s\n", r->dll_name);
3625}
3626
3627static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3628 TALLOC_CTX *mem_ctx, int argc,
3629 const char **argv)
3630{
3631 WERROR werror;
3632 uint32_t count, level = 1, i;
3633 union spoolss_MonitorInfo *info;
3634
3635 /* Parse the command arguments */
3636
3637 if (argc > 2) {
3638 printf("Usage: %s [level]\n", argv[0]);
3639 return WERR_OK;
3640 }
3641
3642 if (argc == 2) {
3643 level = atoi(argv[1]);
3644 }
3645
3646 /* Enumerate Print Monitors */
3647
3648 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3649 cli->srv_name_slash,
3650 level,
3651 0,
3652 &count,
3653 &info);
3654 if (!W_ERROR_IS_OK(werror)) {
3655 goto done;
3656 }
3657
3658 /* Display output */
3659
3660 for (i = 0; i < count; i++) {
3661 switch (level) {
3662 case 1:
3663 display_monitor1(&info[i].info1);
3664 break;
3665 case 2:
3666 display_monitor2(&info[i].info2);
3667 break;
3668 }
3669 }
3670
3671 done:
3672 return werror;
3673}
3674
3675static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3676 TALLOC_CTX *mem_ctx, int argc,
3677 const char **argv)
3678{
3679 WERROR result;
3680 NTSTATUS status;
3681 struct policy_handle handle, gdi_handle;
3682 const char *printername;
3683 struct spoolss_DevmodeContainer devmode_ctr;
3684 struct dcerpc_binding_handle *b = cli->binding_handle;
3685
3686 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3687
3688 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3689 printername,
3690 SEC_FLAG_MAXIMUM_ALLOWED,
3691 &handle);
3692 if (!W_ERROR_IS_OK(result)) {
3693 return result;
3694 }
3695
3696 ZERO_STRUCT(devmode_ctr);
3697
3698 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3699 &handle,
3700 &gdi_handle,
3701 &devmode_ctr,
3702 &result);
3703 if (!NT_STATUS_IS_OK(status)) {
3704 result = ntstatus_to_werror(status);
3705 goto done;
3706 }
3707 if (!W_ERROR_IS_OK(result)) {
3708 goto done;
3709 }
3710
3711 done:
3712 if (is_valid_policy_hnd(&gdi_handle)) {
3713 WERROR _result;
3714 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3715 }
3716 if (is_valid_policy_hnd(&handle)) {
3717 WERROR _result;
3718 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3719 }
3720
3721 return result;
3722}
3723
3724/* List of commands exported by this module */
3725struct cmd_set spoolss_commands[] = {
3726
3727 { "SPOOLSS" },
3728
3729 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3730 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3731 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3732 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3733 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3734 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3735 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3736 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3737 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3738 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3739 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3740 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3741 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3742 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3743 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3744 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3745 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3746 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3747 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3748 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3749 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3750 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3751 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3752 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3753 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3754 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3755 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3756 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3757 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3758 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3759 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3760 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3761 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3762 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3763 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3764 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3765
3766 { NULL }
3767};
Note: See TracBrowser for help on using the repository browser.