source: branches/samba-3.5.x/source3/rpcclient/cmd_spoolss.c

Last change on this file was 596, checked in by Herwig Bauernfeind, 14 years ago

Samba 3.5: Update trunk to 3.5.8

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