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