s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open_noauth().
[amitay/samba.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)) {
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
867                 if (strequal(v, "OsVersion")) {
868                         struct spoolss_OSVersion os;
869                         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
870                                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
871                         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
872                                 printf("%s: OsVersion:\n", v);
873                                 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
874                         }
875                 }
876                 if (strequal(v, "OsVersionEx")) {
877                         struct spoolss_OSVersionEx os;
878                         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
879                                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
880                         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
881                                 printf("%s: OsVersionEx:\n", v);
882                                 NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
883                         }
884                 }
885                 break;
886         }
887         case REG_MULTI_SZ:
888                 printf("%s: REG_MULTI_SZ: ", v);
889                 for (i=0; r.string_array[i] != NULL; i++) {
890                         printf("%s ", r.string_array[i]);
891                 }
892                 printf("\n");
893                 break;
894         default:
895                 printf("%s: unknown type 0x%02x:\n", v, type);
896                 break;
897         }
898 }
899
900 /****************************************************************************
901 ****************************************************************************/
902
903 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
904                                            TALLOC_CTX *mem_ctx,
905                                            int argc, const char **argv)
906 {
907         struct policy_handle pol;
908         WERROR          result;
909         fstring         printername;
910         const char *valuename;
911         enum winreg_Type type;
912         uint8_t *data;
913         uint32_t needed;
914         struct dcerpc_binding_handle *b = cli->binding_handle;
915
916         if (argc != 3) {
917                 printf("Usage: %s <printername> <valuename>\n", argv[0]);
918                 printf("<printername> of . queries print server\n");
919                 return WERR_OK;
920         }
921         valuename = argv[2];
922
923         /* Open a printer handle */
924
925         if (strncmp(argv[1], ".", sizeof(".")) == 0)
926                 fstrcpy(printername, cli->srv_name_slash);
927         else
928                 slprintf(printername, sizeof(printername)-1, "%s\\%s",
929                           cli->srv_name_slash, argv[1]);
930
931         /* get a printer handle */
932
933         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
934                                                printername,
935                                                SEC_FLAG_MAXIMUM_ALLOWED,
936                                                &pol);
937         if (!W_ERROR_IS_OK(result))
938                 goto done;
939
940         /* Get printer info */
941
942         result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
943                                                &pol,
944                                                valuename,
945                                                0,
946                                                &type,
947                                                &needed,
948                                                &data);
949         if (!W_ERROR_IS_OK(result))
950                 goto done;
951
952         /* Display printer data */
953
954         display_printer_data(valuename, type, data, needed);
955
956  done:
957         if (is_valid_policy_hnd(&pol)) {
958                 WERROR _result;
959                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
960         }
961
962         return result;
963 }
964
965 /****************************************************************************
966 ****************************************************************************/
967
968 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
969                                              TALLOC_CTX *mem_ctx,
970                                              int argc, const char **argv)
971 {
972         struct policy_handle pol;
973         WERROR          result;
974         NTSTATUS        status;
975         fstring         printername;
976         const char *valuename, *keyname;
977
978         enum winreg_Type type;
979         uint8_t *data = NULL;
980         uint32_t offered = 0;
981         uint32_t needed;
982         struct dcerpc_binding_handle *b = cli->binding_handle;
983
984         if (argc != 4) {
985                 printf("Usage: %s <printername> <keyname> <valuename>\n",
986                        argv[0]);
987                 printf("<printername> of . queries print server\n");
988                 return WERR_OK;
989         }
990         valuename = argv[3];
991         keyname = argv[2];
992
993         /* Open a printer handle */
994
995         if (strncmp(argv[1], ".", sizeof(".")) == 0)
996                 fstrcpy(printername, cli->srv_name_slash);
997         else
998                 slprintf(printername, sizeof(printername)-1, "%s\\%s",
999                           cli->srv_name_slash, argv[1]);
1000
1001         /* get a printer handle */
1002
1003         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1004                                                printername,
1005                                                SEC_FLAG_MAXIMUM_ALLOWED,
1006                                                &pol);
1007         if (!W_ERROR_IS_OK(result))
1008                 goto done;
1009
1010         /* Get printer info */
1011
1012         data = talloc_zero_array(mem_ctx, uint8_t, offered);
1013         if (!data) {
1014                 goto done;
1015         }
1016
1017         status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1018                                                  &pol,
1019                                                  keyname,
1020                                                  valuename,
1021                                                  &type,
1022                                                  data,
1023                                                  offered,
1024                                                  &needed,
1025                                                  &result);
1026         if (!NT_STATUS_IS_OK(status)) {
1027                 result = ntstatus_to_werror(status);
1028                 goto done;
1029         }
1030         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1031                 offered = needed;
1032                 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1033                 if (!data) {
1034                         goto done;
1035                 }
1036                 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1037                                                          &pol,
1038                                                          keyname,
1039                                                          valuename,
1040                                                          &type,
1041                                                          data,
1042                                                          offered,
1043                                                          &needed,
1044                                                          &result);
1045         }
1046
1047         if (!NT_STATUS_IS_OK(status)) {
1048                 result = ntstatus_to_werror(status);
1049                 goto done;
1050         }
1051
1052         if (!W_ERROR_IS_OK(result))
1053                 goto done;
1054
1055         /* Display printer data */
1056
1057         display_printer_data(valuename, type, data, needed);
1058
1059
1060  done:
1061         if (is_valid_policy_hnd(&pol)) {
1062                 WERROR _result;
1063                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1064         }
1065
1066         return result;
1067 }
1068
1069 /****************************************************************************
1070 ****************************************************************************/
1071
1072 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1073 {
1074         if (!r) {
1075                 return;
1076         }
1077
1078         printf("Printer Driver Info 1:\n");
1079         printf("\tDriver Name: [%s]\n", r->driver_name);
1080         printf("\n");
1081 }
1082
1083 /****************************************************************************
1084 ****************************************************************************/
1085
1086 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1087 {
1088         if (!r) {
1089                 return;
1090         }
1091
1092         printf("Printer Driver Info 2:\n");
1093         printf("\tVersion: [%x]\n", r->version);
1094         printf("\tDriver Name: [%s]\n", r->driver_name);
1095         printf("\tArchitecture: [%s]\n", r->architecture);
1096         printf("\tDriver Path: [%s]\n", r->driver_path);
1097         printf("\tDatafile: [%s]\n", r->data_file);
1098         printf("\tConfigfile: [%s]\n", r->config_file);
1099         printf("\n");
1100 }
1101
1102 /****************************************************************************
1103 ****************************************************************************/
1104
1105 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1106 {
1107         int i;
1108
1109         if (!r) {
1110                 return;
1111         }
1112
1113         printf("Printer Driver Info 3:\n");
1114         printf("\tVersion: [%x]\n", r->version);
1115         printf("\tDriver Name: [%s]\n", r->driver_name);
1116         printf("\tArchitecture: [%s]\n", r->architecture);
1117         printf("\tDriver Path: [%s]\n", r->driver_path);
1118         printf("\tDatafile: [%s]\n", r->data_file);
1119         printf("\tConfigfile: [%s]\n", r->config_file);
1120         printf("\tHelpfile: [%s]\n", r->help_file);
1121
1122         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1123                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1124         }
1125
1126         printf("\tMonitorname: [%s]\n", r->monitor_name);
1127         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1128         printf("\n");
1129 }
1130
1131 /****************************************************************************
1132 ****************************************************************************/
1133
1134 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1135 {
1136         int i;
1137
1138         if (!r) {
1139                 return;
1140         }
1141
1142         printf("Printer Driver Info 4:\n");
1143         printf("\tVersion: [%x]\n", r->version);
1144         printf("\tDriver Name: [%s]\n", r->driver_name);
1145         printf("\tArchitecture: [%s]\n", r->architecture);
1146         printf("\tDriver Path: [%s]\n", r->driver_path);
1147         printf("\tDatafile: [%s]\n", r->data_file);
1148         printf("\tConfigfile: [%s]\n", r->config_file);
1149         printf("\tHelpfile: [%s]\n", r->help_file);
1150
1151         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1152                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1153         }
1154
1155         printf("\tMonitorname: [%s]\n", r->monitor_name);
1156         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1157
1158         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1159                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1160         }
1161         printf("\n");
1162 }
1163
1164 /****************************************************************************
1165 ****************************************************************************/
1166
1167 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1168 {
1169         if (!r) {
1170                 return;
1171         }
1172
1173         printf("Printer Driver Info 5:\n");
1174         printf("\tVersion: [%x]\n", r->version);
1175         printf("\tDriver Name: [%s]\n", r->driver_name);
1176         printf("\tArchitecture: [%s]\n", r->architecture);
1177         printf("\tDriver Path: [%s]\n", r->driver_path);
1178         printf("\tDatafile: [%s]\n", r->data_file);
1179         printf("\tConfigfile: [%s]\n", r->config_file);
1180         printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1181         printf("\tConfig Version: [0x%x]\n", r->config_version);
1182         printf("\tDriver Version: [0x%x]\n", r->driver_version);
1183         printf("\n");
1184 }
1185
1186 /****************************************************************************
1187 ****************************************************************************/
1188
1189 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1190 {
1191         int i;
1192
1193         if (!r) {
1194                 return;
1195         }
1196
1197         printf("Printer Driver Info 6:\n");
1198         printf("\tVersion: [%x]\n", r->version);
1199         printf("\tDriver Name: [%s]\n", r->driver_name);
1200         printf("\tArchitecture: [%s]\n", r->architecture);
1201         printf("\tDriver Path: [%s]\n", r->driver_path);
1202         printf("\tDatafile: [%s]\n", r->data_file);
1203         printf("\tConfigfile: [%s]\n", r->config_file);
1204         printf("\tHelpfile: [%s]\n", r->help_file);
1205
1206         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1207                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1208         }
1209
1210         printf("\tMonitorname: [%s]\n", r->monitor_name);
1211         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1212
1213         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1214                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1215         }
1216
1217         printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1218         printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1219         printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1220         printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1221         printf("\tHardware ID: [%s]\n", r->hardware_id);
1222         printf("\tProvider: [%s]\n", r->provider);
1223
1224         printf("\n");
1225 }
1226
1227 /****************************************************************************
1228 ****************************************************************************/
1229
1230 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1231 {
1232         int i;
1233
1234         if (!r) {
1235                 return;
1236         }
1237
1238         printf("Printer Driver Info 8:\n");
1239         printf("\tVersion: [%x]\n", r->version);
1240         printf("\tDriver Name: [%s]\n", r->driver_name);
1241         printf("\tArchitecture: [%s]\n", r->architecture);
1242         printf("\tDriver Path: [%s]\n", r->driver_path);
1243         printf("\tDatafile: [%s]\n", r->data_file);
1244         printf("\tConfigfile: [%s]\n", r->config_file);
1245         printf("\tHelpfile: [%s]\n", r->help_file);
1246         printf("\tMonitorname: [%s]\n", r->monitor_name);
1247         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1248
1249         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1250                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1251         }
1252
1253         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1254                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1255         }
1256
1257         printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1258         printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1259         printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1260         printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1261         printf("\tHardware ID: [%s]\n", r->hardware_id);
1262         printf("\tProvider: [%s]\n", r->provider);
1263         printf("\tPrint Processor: [%s]\n", r->print_processor);
1264         printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1265         for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1266                 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1267         }
1268         printf("\tInf Path: [%s]\n", r->inf_path);
1269         printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1270         for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1271                 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1272         }
1273         printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1274         printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1275                 (long long unsigned int)r->min_inbox_driver_ver_version);
1276
1277         printf("\n");
1278 }
1279
1280 /****************************************************************************
1281 ****************************************************************************/
1282
1283 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1284                                     TALLOC_CTX *mem_ctx,
1285                                     int argc, const char **argv)
1286 {
1287         struct policy_handle pol;
1288         WERROR          werror;
1289         uint32_t        level = 3;
1290         const char      *printername;
1291         uint32_t        i;
1292         bool            success = false;
1293         union spoolss_DriverInfo info;
1294         uint32_t server_major_version;
1295         uint32_t server_minor_version;
1296         struct dcerpc_binding_handle *b = cli->binding_handle;
1297
1298         if ((argc == 1) || (argc > 3)) {
1299                 printf("Usage: %s <printername> [level]\n", argv[0]);
1300                 return WERR_OK;
1301         }
1302
1303         /* get the arguments need to open the printer handle */
1304
1305         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1306
1307         if (argc == 3) {
1308                 level = atoi(argv[2]);
1309         }
1310
1311         /* Open a printer handle */
1312
1313         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1314                                                printername,
1315                                                PRINTER_ACCESS_USE,
1316                                                &pol);
1317         if (!W_ERROR_IS_OK(werror)) {
1318                 printf("Error opening printer handle for %s!\n", printername);
1319                 return werror;
1320         }
1321
1322         /* loop through and print driver info level for each architecture */
1323
1324         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1325
1326                 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1327                                                           &pol,
1328                                                           archi_table[i].long_archi,
1329                                                           level,
1330                                                           0, /* offered */
1331                                                           archi_table[i].version,
1332                                                           2,
1333                                                           &info,
1334                                                           &server_major_version,
1335                                                           &server_minor_version);
1336                 if (!W_ERROR_IS_OK(werror)) {
1337                         continue;
1338                 }
1339
1340                 /* need at least one success */
1341
1342                 success = true;
1343
1344                 printf("\n[%s]\n", archi_table[i].long_archi);
1345
1346                 switch (level) {
1347                 case 1:
1348                         display_print_driver1(&info.info1);
1349                         break;
1350                 case 2:
1351                         display_print_driver2(&info.info2);
1352                         break;
1353                 case 3:
1354                         display_print_driver3(&info.info3);
1355                         break;
1356                 case 4:
1357                         display_print_driver4(&info.info4);
1358                         break;
1359                 case 5:
1360                         display_print_driver5(&info.info5);
1361                         break;
1362                 case 6:
1363                         display_print_driver6(&info.info6);
1364                         break;
1365                 case 8:
1366                         display_print_driver8(&info.info8);
1367                         break;
1368                 default:
1369                         printf("unknown info level %d\n", level);
1370                         break;
1371                 }
1372         }
1373
1374         /* Cleanup */
1375
1376         if (is_valid_policy_hnd(&pol)) {
1377                 WERROR _result;
1378                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1379         }
1380
1381         if (success) {
1382                 werror = WERR_OK;
1383         }
1384
1385         return werror;
1386 }
1387
1388 /****************************************************************************
1389 ****************************************************************************/
1390
1391 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1392                                           TALLOC_CTX *mem_ctx,
1393                                           const char *architecture,
1394                                           uint32_t level)
1395 {
1396         WERROR werror;
1397         uint32_t count = 0;
1398         union spoolss_DriverInfo *info = NULL;
1399         uint32_t j;
1400
1401         werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1402                                                    cli->srv_name_slash,
1403                                                    architecture,
1404                                                    level,
1405                                                    0,
1406                                                    &count,
1407                                                    &info);
1408
1409         if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1410                 printf("Server does not support environment [%s]\n",
1411                         architecture);
1412                 return WERR_OK;
1413         }
1414
1415         if (count == 0) {
1416                 return WERR_OK;
1417         }
1418
1419         if (!W_ERROR_IS_OK(werror)) {
1420                 printf("Error getting driver for environment [%s] - %s\n",
1421                         architecture, win_errstr(werror));
1422                 return werror;
1423         }
1424
1425         printf("\n[%s]\n", architecture);
1426
1427         switch (level) {
1428         case 1:
1429                 for (j=0; j < count; j++) {
1430                         display_print_driver1(&info[j].info1);
1431                 }
1432                 break;
1433         case 2:
1434                 for (j=0; j < count; j++) {
1435                         display_print_driver2(&info[j].info2);
1436                 }
1437                 break;
1438         case 3:
1439                 for (j=0; j < count; j++) {
1440                         display_print_driver3(&info[j].info3);
1441                 }
1442                 break;
1443         case 4:
1444                 for (j=0; j < count; j++) {
1445                         display_print_driver4(&info[j].info4);
1446                 }
1447                 break;
1448         case 5:
1449                 for (j=0; j < count; j++) {
1450                         display_print_driver5(&info[j].info5);
1451                 }
1452                 break;
1453         case 6:
1454                 for (j=0; j < count; j++) {
1455                         display_print_driver6(&info[j].info6);
1456                 }
1457                 break;
1458         case 8:
1459                 for (j=0; j < count; j++) {
1460                         display_print_driver8(&info[j].info8);
1461                 }
1462                 break;
1463         default:
1464                 printf("unknown info level %d\n", level);
1465                 return WERR_UNKNOWN_LEVEL;
1466         }
1467
1468         return werror;
1469 }
1470
1471 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1472                                          TALLOC_CTX *mem_ctx,
1473                                          int argc, const char **argv)
1474 {
1475         WERROR werror = WERR_OK;
1476         uint32_t        level = 1;
1477         uint32_t        i;
1478         const char *architecture = NULL;
1479
1480         if (argc > 3) {
1481                 printf("Usage: enumdrivers [level] [architecture]\n");
1482                 return WERR_OK;
1483         }
1484
1485         if (argc >= 2) {
1486                 level = atoi(argv[1]);
1487         }
1488
1489         if (argc == 3) {
1490                 architecture = argv[2];
1491         }
1492
1493         if (architecture) {
1494                 return enum_driver_by_architecture(cli, mem_ctx,
1495                                                    architecture,
1496                                                    level);
1497         }
1498
1499         /* loop through and print driver info level for each architecture */
1500         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1501                 /* check to see if we already asked for this architecture string */
1502
1503                 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1504                         continue;
1505                 }
1506
1507                 werror = enum_driver_by_architecture(cli, mem_ctx,
1508                                                      archi_table[i].long_archi,
1509                                                      level);
1510                 if (!W_ERROR_IS_OK(werror)) {
1511                         break;
1512                 }
1513         }
1514
1515         return werror;
1516 }
1517
1518 /****************************************************************************
1519 ****************************************************************************/
1520
1521 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1522 {
1523         printf("\tDirectory Name:[%s]\n", r->directory_name);
1524 }
1525
1526 /****************************************************************************
1527 ****************************************************************************/
1528
1529 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1530                                          TALLOC_CTX *mem_ctx,
1531                                          int argc, const char **argv)
1532 {
1533         WERROR result;
1534         NTSTATUS status;
1535         const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1536         DATA_BLOB buffer;
1537         uint32_t offered;
1538         union spoolss_DriverDirectoryInfo info;
1539         uint32_t needed;
1540         struct dcerpc_binding_handle *b = cli->binding_handle;
1541
1542         if (argc > 2) {
1543                 printf("Usage: %s [environment]\n", argv[0]);
1544                 return WERR_OK;
1545         }
1546
1547         /* Get the arguments need to open the printer handle */
1548
1549         if (argc == 2) {
1550                 env = argv[1];
1551         }
1552
1553         /* Get the directory.  Only use Info level 1 */
1554
1555         status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1556                                                           cli->srv_name_slash,
1557                                                           env,
1558                                                           1,
1559                                                           NULL, /* buffer */
1560                                                           0, /* offered */
1561                                                           NULL, /* info */
1562                                                           &needed,
1563                                                           &result);
1564         if (!NT_STATUS_IS_OK(status)) {
1565                 return ntstatus_to_werror(status);
1566         }
1567         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1568                 offered = needed;
1569                 buffer = data_blob_talloc_zero(mem_ctx, needed);
1570
1571                 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1572                                                                   cli->srv_name_slash,
1573                                                                   env,
1574                                                                   1,
1575                                                                   &buffer,
1576                                                                   offered,
1577                                                                   &info,
1578                                                                   &needed,
1579                                                                   &result);
1580                 if (!NT_STATUS_IS_OK(status)) {
1581                         return ntstatus_to_werror(status);
1582                 }
1583         }
1584
1585         if (W_ERROR_IS_OK(result)) {
1586                 display_printdriverdir_1(&info.info1);
1587         }
1588
1589         return result;
1590 }
1591
1592 /****************************************************************************
1593 ****************************************************************************/
1594
1595 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1596                                struct spoolss_AddDriverInfo3 *info,
1597                                const char *arch)
1598 {
1599
1600         int i;
1601
1602         for (i=0; archi_table[i].long_archi != NULL; i++)
1603         {
1604                 if (strcmp(arch, archi_table[i].short_archi) == 0)
1605                 {
1606                         info->version = archi_table[i].version;
1607                         info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1608                         break;
1609                 }
1610         }
1611
1612         if (archi_table[i].long_archi == NULL)
1613         {
1614                 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1615         }
1616
1617         return;
1618 }
1619
1620
1621 /**************************************************************************
1622  wrapper for strtok to get the next parameter from a delimited list.
1623  Needed to handle the empty parameter string denoted by "NULL"
1624  *************************************************************************/
1625
1626 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1627                                 const char *delim, const char **dest,
1628                                 char **saveptr)
1629 {
1630         char    *ptr;
1631
1632         /* get the next token */
1633         ptr = strtok_r(str, delim, saveptr);
1634
1635         /* a string of 'NULL' is used to represent an empty
1636            parameter because two consecutive delimiters
1637            will not return an empty string.  See man strtok(3)
1638            for details */
1639         if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1640                 ptr = NULL;
1641         }
1642
1643         if (dest != NULL) {
1644                 *dest = talloc_strdup(mem_ctx, ptr);
1645         }
1646
1647         return ptr;
1648 }
1649
1650 /********************************************************************************
1651  fill in the members of a spoolss_AddDriverInfo3 struct using a character
1652  string in the form of
1653          <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1654              <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1655              <Default Data Type>:<Comma Separated list of Files>
1656  *******************************************************************************/
1657
1658 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1659                                     char *args)
1660 {
1661         char    *str, *str2;
1662         int count = 0;
1663         char *saveptr = NULL;
1664         struct spoolss_StringArray *deps;
1665         const char **file_array = NULL;
1666         int i;
1667
1668         /* fill in the UNISTR fields */
1669         str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1670         str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1671         str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1672         str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1673         str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1674         str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1675         str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1676
1677         /* <Comma Separated List of Dependent Files> */
1678         /* save the beginning of the string */
1679         str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1680         str = str2;
1681
1682         /* begin to strip out each filename */
1683         str = strtok_r(str, ",", &saveptr);
1684
1685         /* no dependent files, we are done */
1686         if (!str) {
1687                 return true;
1688         }
1689
1690         deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1691         if (!deps) {
1692                 return false;
1693         }
1694
1695         while (str != NULL) {
1696                 bool ok;
1697                 ok = add_string_to_array(deps, str, &file_array, &count);
1698                 if (!ok) {
1699                         return false;
1700                 }
1701                 str = strtok_r(NULL, ",", &saveptr);
1702         }
1703
1704         deps->string = talloc_zero_array(deps, const char *, count + 1);
1705         if (!deps->string) {
1706                 return false;
1707         }
1708
1709         for (i=0; i < count; i++) {
1710                 deps->string[i] = file_array[i];
1711         }
1712
1713         r->dependent_files = deps;
1714
1715         return true;
1716 }
1717
1718 /****************************************************************************
1719 ****************************************************************************/
1720
1721 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1722                                              TALLOC_CTX *mem_ctx,
1723                                              int argc, const char **argv)
1724 {
1725         WERROR result;
1726         NTSTATUS status;
1727         uint32_t                  level = 3;
1728         struct spoolss_AddDriverInfoCtr info_ctr;
1729         struct spoolss_AddDriverInfo3 info3;
1730         const char              *arch;
1731         char                    *driver_args;
1732         struct dcerpc_binding_handle *b = cli->binding_handle;
1733
1734         /* parse the command arguments */
1735         if (argc != 3 && argc != 4)
1736         {
1737                 printf ("Usage: %s <Environment> \\\n", argv[0]);
1738                 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1739                 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1740                 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1741                 printf ("\t[version]\n");
1742
1743             return WERR_OK;
1744         }
1745
1746         /* Fill in the spoolss_AddDriverInfo3 struct */
1747         ZERO_STRUCT(info3);
1748
1749         arch = cmd_spoolss_get_short_archi(argv[1]);
1750         if (!arch) {
1751                 printf ("Error Unknown architecture [%s]\n", argv[1]);
1752                 return WERR_INVALID_PARAM;
1753         }
1754
1755         set_drv_info_3_env(mem_ctx, &info3, arch);
1756
1757         driver_args = talloc_strdup( mem_ctx, argv[2] );
1758         if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1759         {
1760                 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1761                 return WERR_INVALID_PARAM;
1762         }
1763
1764         /* if printer driver version specified, override the default version
1765          * used by the architecture.  This allows installation of Windows
1766          * 2000 (version 3) printer drivers. */
1767         if (argc == 4)
1768         {
1769                 info3.version = atoi(argv[3]);
1770         }
1771
1772
1773         info_ctr.level          = level;
1774         info_ctr.info.info3     = &info3;
1775
1776         status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1777                                                  cli->srv_name_slash,
1778                                                  &info_ctr,
1779                                                  &result);
1780         if (!NT_STATUS_IS_OK(status)) {
1781                 return ntstatus_to_werror(status);
1782         }
1783         if (W_ERROR_IS_OK(result)) {
1784                 printf ("Printer Driver %s successfully installed.\n",
1785                         info3.driver_name);
1786         }
1787
1788         return result;
1789 }
1790
1791
1792 /****************************************************************************
1793 ****************************************************************************/
1794
1795 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1796                                          TALLOC_CTX *mem_ctx,
1797                                          int argc, const char **argv)
1798 {
1799         WERROR result;
1800         struct spoolss_SetPrinterInfoCtr info_ctr;
1801         struct spoolss_SetPrinterInfo2 info2;
1802
1803         /* parse the command arguments */
1804         if (argc != 5)
1805         {
1806                 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1807                 return WERR_OK;
1808         }
1809
1810         /* Fill in the DRIVER_INFO_2 struct */
1811         ZERO_STRUCT(info2);
1812
1813         info2.printername       = argv[1];
1814         info2.drivername        = argv[3];
1815         info2.sharename         = argv[2];
1816         info2.portname          = argv[4];
1817         info2.comment           = "Created by rpcclient";
1818         info2.printprocessor    = "winprint";
1819         info2.datatype          = "RAW";
1820         info2.devmode_ptr       = NULL;
1821         info2.secdesc_ptr       = NULL;
1822         info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
1823         info2.priority          = 0;
1824         info2.defaultpriority   = 0;
1825         info2.starttime         = 0;
1826         info2.untiltime         = 0;
1827
1828         /* These three fields must not be used by AddPrinter()
1829            as defined in the MS Platform SDK documentation..
1830            --jerry
1831         info2.status            = 0;
1832         info2.cjobs             = 0;
1833         info2.averageppm        = 0;
1834         */
1835
1836         info_ctr.level = 2;
1837         info_ctr.info.info2 = &info2;
1838
1839         result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1840                                              &info_ctr);
1841         if (W_ERROR_IS_OK(result))
1842                 printf ("Printer %s successfully installed.\n", argv[1]);
1843
1844         return result;
1845 }
1846
1847 /****************************************************************************
1848 ****************************************************************************/
1849
1850 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1851                                       TALLOC_CTX *mem_ctx,
1852                                       int argc, const char **argv)
1853 {
1854         struct policy_handle    pol;
1855         WERROR                  result;
1856         NTSTATUS                status;
1857         uint32_t                level = 2;
1858         const char              *printername;
1859         union spoolss_PrinterInfo info;
1860         struct spoolss_SetPrinterInfoCtr info_ctr;
1861         struct spoolss_SetPrinterInfo2 info2;
1862         struct spoolss_DevmodeContainer devmode_ctr;
1863         struct sec_desc_buf secdesc_ctr;
1864         struct dcerpc_binding_handle *b = cli->binding_handle;
1865
1866         ZERO_STRUCT(devmode_ctr);
1867         ZERO_STRUCT(secdesc_ctr);
1868
1869         /* parse the command arguments */
1870         if (argc != 3)
1871         {
1872                 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1873                 return WERR_OK;
1874         }
1875
1876         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1877
1878         /* Get a printer handle */
1879
1880         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1881                                                printername,
1882                                                PRINTER_ALL_ACCESS,
1883                                                &pol);
1884         if (!W_ERROR_IS_OK(result))
1885                 goto done;
1886
1887         /* Get printer info */
1888
1889         result = rpccli_spoolss_getprinter(cli, mem_ctx,
1890                                            &pol,
1891                                            level,
1892                                            0,
1893                                            &info);
1894         if (!W_ERROR_IS_OK(result)) {
1895                 printf ("Unable to retrieve printer information!\n");
1896                 goto done;
1897         }
1898
1899         /* Set the printer driver */
1900
1901         spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1902         info2.drivername = argv[2];
1903
1904         info_ctr.level = 2;
1905         info_ctr.info.info2 = &info2;
1906
1907         status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1908                                            &pol,
1909                                            &info_ctr,
1910                                            &devmode_ctr,
1911                                            &secdesc_ctr,
1912                                            0, /* command */
1913                                            &result);
1914         if (!NT_STATUS_IS_OK(status)) {
1915                 result = ntstatus_to_werror(status);
1916                 goto done;
1917         }
1918         if (!W_ERROR_IS_OK(result)) {
1919                 printf("SetPrinter call failed!\n");
1920                 goto done;
1921         }
1922
1923         printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1924
1925 done:
1926         /* Cleanup */
1927
1928         if (is_valid_policy_hnd(&pol)) {
1929                 WERROR _result;
1930                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1931         }
1932
1933         return result;
1934 }
1935
1936
1937 /****************************************************************************
1938 ****************************************************************************/
1939
1940 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1941                                          TALLOC_CTX *mem_ctx,
1942                                          int argc, const char **argv)
1943 {
1944         WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1945         NTSTATUS status;
1946         struct dcerpc_binding_handle *b = cli->binding_handle;
1947
1948         int   i;
1949         int vers = -1;
1950
1951         const char *arch = NULL;
1952         uint32_t delete_flags = 0;
1953
1954         /* parse the command arguments */
1955         if (argc < 2 || argc > 5) {
1956                 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
1957                 return WERR_OK;
1958         }
1959
1960         if (argc >= 3)
1961                 arch = argv[2];
1962         if (argc >= 4) {
1963                 vers = atoi(argv[3]);
1964                 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1965         }
1966         if (argc == 5)
1967                 delete_flags = atoi(argv[4]);
1968
1969         /* delete the driver for all architectures */
1970         for (i=0; archi_table[i].long_archi; i++) {
1971
1972                 if (arch && !strequal(archi_table[i].long_archi, arch))
1973                         continue;
1974
1975                 if (vers >= 0 && archi_table[i].version != vers)
1976                         continue;
1977
1978                 /* make the call to remove the driver */
1979                 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1980                                                               cli->srv_name_slash,
1981                                                               archi_table[i].long_archi,
1982                                                               argv[1],
1983                                                               delete_flags,
1984                                                               archi_table[i].version,
1985                                                               &result);
1986                 if (!NT_STATUS_IS_OK(status)) {
1987                         return ntstatus_to_werror(status);
1988                 }
1989                 if ( !W_ERROR_IS_OK(result) )
1990                 {
1991                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1992                                 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1993                                         argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1994                         }
1995                 }
1996                 else
1997                 {
1998                         printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1999                         archi_table[i].long_archi, archi_table[i].version);
2000                         ret = WERR_OK;
2001                 }
2002         }
2003
2004         return ret;
2005 }
2006
2007
2008 /****************************************************************************
2009 ****************************************************************************/
2010
2011 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2012                                          TALLOC_CTX *mem_ctx,
2013                                          int argc, const char **argv)
2014 {
2015         WERROR result = WERR_OK;
2016         NTSTATUS status;
2017         int                     i;
2018         struct dcerpc_binding_handle *b = cli->binding_handle;
2019
2020         /* parse the command arguments */
2021         if (argc != 2) {
2022                 printf ("Usage: %s <driver>\n", argv[0]);
2023                 return WERR_OK;
2024         }
2025
2026         /* delete the driver for all architectures */
2027         for (i=0; archi_table[i].long_archi; i++) {
2028                 result = WERR_OK;
2029
2030                 /* make the call to remove the driver */
2031                 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2032                                                             cli->srv_name_slash,
2033                                                             archi_table[i].long_archi,
2034                                                             argv[1],
2035                                                             &result);
2036                 if (!NT_STATUS_IS_OK(status)) {
2037                         result = ntstatus_to_werror(status);
2038                         continue;
2039                 }
2040                 if ( !W_ERROR_IS_OK(result) ) {
2041                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2042                                 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2043                                         argv[1], archi_table[i].long_archi,
2044                                         win_errstr(result));
2045                         }
2046                 } else {
2047                         printf ("Driver %s removed for arch [%s].\n", argv[1],
2048                                 archi_table[i].long_archi);
2049                 }
2050         }
2051
2052         return result;
2053 }
2054
2055 /****************************************************************************
2056 ****************************************************************************/
2057
2058 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2059                                             TALLOC_CTX *mem_ctx,
2060                                             int argc, const char **argv)
2061 {
2062         WERROR result;
2063         NTSTATUS status;
2064         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2065         DATA_BLOB buffer;
2066         uint32_t offered;
2067         union spoolss_PrintProcessorDirectoryInfo info;
2068         uint32_t needed;
2069         struct dcerpc_binding_handle *b = cli->binding_handle;
2070
2071         /* parse the command arguments */
2072         if (argc > 2) {
2073                 printf ("Usage: %s [environment]\n", argv[0]);
2074                 return WERR_OK;
2075         }
2076
2077         if (argc == 2) {
2078                 environment = argv[1];
2079         }
2080
2081         status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2082                                                            cli->srv_name_slash,
2083                                                            environment,
2084                                                            1,
2085                                                            NULL, /* buffer */
2086                                                            0, /* offered */
2087                                                            NULL, /* info */
2088                                                            &needed,
2089                                                            &result);
2090         if (!NT_STATUS_IS_OK(status)) {
2091                 return ntstatus_to_werror(status);
2092         }
2093         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2094                 offered = needed;
2095                 buffer = data_blob_talloc_zero(mem_ctx, needed);
2096
2097                 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2098                                                                    cli->srv_name_slash,
2099                                                                    environment,
2100                                                                    1,
2101                                                                    &buffer,
2102                                                                    offered,
2103                                                                    &info,
2104                                                                    &needed,
2105                                                                    &result);
2106                 if (!NT_STATUS_IS_OK(status)) {
2107                         return ntstatus_to_werror(status);
2108                 }
2109         }
2110
2111         if (W_ERROR_IS_OK(result)) {
2112                 printf("%s\n", info.info1.directory_name);
2113         }
2114
2115         return result;
2116 }
2117
2118 /****************************************************************************
2119 ****************************************************************************/
2120
2121 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2122                                     int argc, const char **argv)
2123 {
2124         struct policy_handle handle;
2125         WERROR werror;
2126         NTSTATUS status;
2127         const char *printername;
2128         struct spoolss_AddFormInfoCtr info_ctr;
2129         struct spoolss_AddFormInfo1 info1;
2130         struct spoolss_AddFormInfo2 info2;
2131         uint32_t level = 1;
2132         struct dcerpc_binding_handle *b = cli->binding_handle;
2133
2134         /* Parse the command arguments */
2135
2136         if (argc < 3 || argc > 5) {
2137                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2138                 return WERR_OK;
2139         }
2140
2141         /* Get a printer handle */
2142
2143         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2144
2145         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2146                                                printername,
2147                                                PRINTER_ALL_ACCESS,
2148                                                &handle);
2149         if (!W_ERROR_IS_OK(werror))
2150                 goto done;
2151
2152         /* Dummy up some values for the form data */
2153
2154         if (argc == 4) {
2155                 level = atoi(argv[3]);
2156         }
2157
2158         switch (level) {
2159         case 1:
2160                 info1.flags             = SPOOLSS_FORM_USER;
2161                 info1.form_name         = argv[2];
2162                 info1.size.width        = 100;
2163                 info1.size.height       = 100;
2164                 info1.area.left         = 0;
2165                 info1.area.top          = 10;
2166                 info1.area.right        = 20;
2167                 info1.area.bottom       = 30;
2168
2169                 info_ctr.level          = 1;
2170                 info_ctr.info.info1     = &info1;
2171
2172                 break;
2173         case 2:
2174                 info2.flags             = SPOOLSS_FORM_USER;
2175                 info2.form_name         = argv[2];
2176                 info2.size.width        = 100;
2177                 info2.size.height       = 100;
2178                 info2.area.left         = 0;
2179                 info2.area.top          = 10;
2180                 info2.area.right        = 20;
2181                 info2.area.bottom       = 30;
2182                 info2.keyword           = argv[2];
2183                 info2.string_type       = SPOOLSS_FORM_STRING_TYPE_NONE;
2184                 info2.mui_dll           = NULL;
2185                 info2.ressource_id      = 0;
2186                 info2.display_name      = argv[2];
2187                 info2.lang_id           = 0;
2188
2189                 info_ctr.level          = 2;
2190                 info_ctr.info.info2     = &info2;
2191
2192                 break;
2193         default:
2194                 werror = WERR_INVALID_PARAM;
2195                 goto done;
2196         }
2197
2198         /* Add the form */
2199
2200         status = dcerpc_spoolss_AddForm(b, mem_ctx,
2201                                         &handle,
2202                                         &info_ctr,
2203                                         &werror);
2204         if (!NT_STATUS_IS_OK(status)) {
2205                 werror = ntstatus_to_werror(status);
2206                 goto done;
2207         }
2208  done:
2209         if (is_valid_policy_hnd(&handle)) {
2210                 WERROR _result;
2211                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2212         }
2213
2214         return werror;
2215 }
2216
2217 /****************************************************************************
2218 ****************************************************************************/
2219
2220 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2221                                     int argc, const char **argv)
2222 {
2223         struct policy_handle handle;
2224         WERROR werror;
2225         NTSTATUS status;
2226         const char *printername;
2227         struct spoolss_AddFormInfoCtr info_ctr;
2228         struct spoolss_AddFormInfo1 info1;
2229         struct dcerpc_binding_handle *b = cli->binding_handle;
2230
2231         /* Parse the command arguments */
2232
2233         if (argc != 3) {
2234                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2235                 return WERR_OK;
2236         }
2237
2238         /* Get a printer handle */
2239
2240         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2241
2242         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2243                                                printername,
2244                                                SEC_FLAG_MAXIMUM_ALLOWED,
2245                                                &handle);
2246         if (!W_ERROR_IS_OK(werror))
2247                 goto done;
2248
2249         /* Dummy up some values for the form data */
2250
2251         info1.flags             = SPOOLSS_FORM_PRINTER;
2252         info1.size.width        = 100;
2253         info1.size.height       = 100;
2254         info1.area.left         = 0;
2255         info1.area.top          = 1000;
2256         info1.area.right        = 2000;
2257         info1.area.bottom       = 3000;
2258         info1.form_name         = argv[2];
2259
2260         info_ctr.info.info1 = &info1;
2261         info_ctr.level = 1;
2262
2263         /* Set the form */
2264
2265         status = dcerpc_spoolss_SetForm(b, mem_ctx,
2266                                         &handle,
2267                                         argv[2],
2268                                         &info_ctr,
2269                                         &werror);
2270         if (!NT_STATUS_IS_OK(status)) {
2271                 werror = ntstatus_to_werror(status);
2272                 goto done;
2273         }
2274  done:
2275         if (is_valid_policy_hnd(&handle)) {
2276                 WERROR _result;
2277                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2278         }
2279
2280         return werror;
2281 }
2282
2283 /****************************************************************************
2284 ****************************************************************************/
2285
2286 static const char *get_form_flag(int form_flag)
2287 {
2288         switch (form_flag) {
2289         case SPOOLSS_FORM_USER:
2290                 return "FORM_USER";
2291         case SPOOLSS_FORM_BUILTIN:
2292                 return "FORM_BUILTIN";
2293         case SPOOLSS_FORM_PRINTER:
2294                 return "FORM_PRINTER";
2295         default:
2296                 return "unknown";
2297         }
2298 }
2299
2300 /****************************************************************************
2301 ****************************************************************************/
2302
2303 static void display_form_info1(struct spoolss_FormInfo1 *r)
2304 {
2305         printf("%s\n" \
2306                 "\tflag: %s (%d)\n" \
2307                 "\twidth: %d, length: %d\n" \
2308                 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2309                 r->form_name, get_form_flag(r->flags), r->flags,
2310                 r->size.width, r->size.height,
2311                 r->area.left, r->area.right,
2312                 r->area.top, r->area.bottom);
2313 }
2314
2315 /****************************************************************************
2316 ****************************************************************************/
2317
2318 static void display_form_info2(struct spoolss_FormInfo2 *r)
2319 {
2320         printf("%s\n" \
2321                 "\tflag: %s (%d)\n" \
2322                 "\twidth: %d, length: %d\n" \
2323                 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2324                 r->form_name, get_form_flag(r->flags), r->flags,
2325                 r->size.width, r->size.height,
2326                 r->area.left, r->area.right,
2327                 r->area.top, r->area.bottom);
2328         printf("\tkeyword: %s\n", r->keyword);
2329         printf("\tstring_type: 0x%08x\n", r->string_type);
2330         printf("\tmui_dll: %s\n", r->mui_dll);
2331         printf("\tressource_id: 0x%08x\n", r->ressource_id);
2332         printf("\tdisplay_name: %s\n", r->display_name);
2333         printf("\tlang_id: %d\n", r->lang_id);
2334         printf("\n");
2335 }
2336
2337 /****************************************************************************
2338 ****************************************************************************/
2339
2340 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2341                                     int argc, const char **argv)
2342 {
2343         struct policy_handle handle;
2344         WERROR werror;
2345         NTSTATUS status;
2346         const char *printername;
2347         DATA_BLOB buffer;
2348         uint32_t offered = 0;
2349         union spoolss_FormInfo info;
2350         uint32_t needed;
2351         uint32_t level = 1;
2352         struct dcerpc_binding_handle *b = cli->binding_handle;
2353
2354         /* Parse the command arguments */
2355
2356         if (argc < 3 || argc > 5) {
2357                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2358                 return WERR_OK;
2359         }
2360
2361         /* Get a printer handle */
2362
2363         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2364
2365         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2366                                                printername,
2367                                                SEC_FLAG_MAXIMUM_ALLOWED,
2368                                                &handle);
2369         if (!W_ERROR_IS_OK(werror))
2370                 goto done;
2371
2372         if (argc == 4) {
2373                 level = atoi(argv[3]);
2374         }
2375
2376         /* Get the form */
2377
2378         status = dcerpc_spoolss_GetForm(b, mem_ctx,
2379                                         &handle,
2380                                         argv[2],
2381                                         level,
2382                                         NULL,
2383                                         offered,
2384                                         &info,
2385                                         &needed,
2386                                         &werror);
2387         if (!NT_STATUS_IS_OK(status)) {
2388                 werror = ntstatus_to_werror(status);
2389                 goto done;
2390         }
2391         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2392                 buffer = data_blob_talloc_zero(mem_ctx, needed);
2393                 offered = needed;
2394                 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2395                                                 &handle,
2396                                                 argv[2],
2397                                                 level,
2398                                                 &buffer,
2399                                                 offered,
2400                                                 &info,
2401                                                 &needed,
2402                                                 &werror);
2403                 if (!NT_STATUS_IS_OK(status)) {
2404                         werror = ntstatus_to_werror(status);
2405                         goto done;
2406                 }
2407         }
2408
2409         if (!W_ERROR_IS_OK(werror)) {
2410                 goto done;
2411         }
2412
2413         switch (level) {
2414         case 1:
2415                 display_form_info1(&info.info1);
2416                 break;
2417         case 2:
2418                 display_form_info2(&info.info2);
2419                 break;
2420         }
2421
2422  done:
2423         if (is_valid_policy_hnd(&handle)) {
2424                 WERROR _result;
2425                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2426         }
2427
2428         return werror;
2429 }
2430
2431 /****************************************************************************
2432 ****************************************************************************/
2433
2434 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2435                                        TALLOC_CTX *mem_ctx, int argc,
2436                                        const char **argv)
2437 {
2438         struct policy_handle handle;
2439         WERROR werror;
2440         NTSTATUS status;
2441         const char *printername;
2442         struct dcerpc_binding_handle *b = cli->binding_handle;
2443
2444         /* Parse the command arguments */
2445
2446         if (argc != 3) {
2447                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2448                 return WERR_OK;
2449         }
2450
2451         /* Get a printer handle */
2452
2453         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2454
2455         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2456                                                printername,
2457                                                SEC_FLAG_MAXIMUM_ALLOWED,
2458                                                &handle);
2459         if (!W_ERROR_IS_OK(werror))
2460                 goto done;
2461
2462         /* Delete the form */
2463
2464         status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2465                                            &handle,
2466                                            argv[2],
2467                                            &werror);
2468         if (!NT_STATUS_IS_OK(status)) {
2469                 werror = ntstatus_to_werror(status);
2470                 goto done;
2471         }
2472
2473  done:
2474         if (is_valid_policy_hnd(&handle)) {
2475                 WERROR _result;
2476                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2477         }
2478
2479         return werror;
2480 }
2481
2482 /****************************************************************************
2483 ****************************************************************************/
2484
2485 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2486                                        TALLOC_CTX *mem_ctx, int argc,
2487                                        const char **argv)
2488 {
2489         struct policy_handle handle;
2490         WERROR werror;
2491         const char *printername;
2492         uint32_t num_forms, level = 1, i;
2493         union spoolss_FormInfo *forms;
2494         struct dcerpc_binding_handle *b = cli->binding_handle;
2495
2496         /* Parse the command arguments */
2497
2498         if (argc < 2 || argc > 4) {
2499                 printf ("Usage: %s <printer> [level]\n", argv[0]);
2500                 return WERR_OK;
2501         }
2502
2503         /* Get a printer handle */
2504
2505         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2506
2507         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2508                                                printername,
2509                                                SEC_FLAG_MAXIMUM_ALLOWED,
2510                                                &handle);
2511         if (!W_ERROR_IS_OK(werror))
2512                 goto done;
2513
2514         if (argc == 3) {
2515                 level = atoi(argv[2]);
2516         }
2517
2518         /* Enumerate forms */
2519
2520         werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2521                                           &handle,
2522                                           level,
2523                                           0,
2524                                           &num_forms,
2525                                           &forms);
2526
2527         if (!W_ERROR_IS_OK(werror))
2528                 goto done;
2529
2530         /* Display output */
2531
2532         for (i = 0; i < num_forms; i++) {
2533                 switch (level) {
2534                 case 1:
2535                         display_form_info1(&forms[i].info1);
2536                         break;
2537                 case 2:
2538                         display_form_info2(&forms[i].info2);
2539                         break;
2540                 }
2541         }
2542
2543  done:
2544         if (is_valid_policy_hnd(&handle)) {
2545                 WERROR _result;
2546                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2547         }
2548
2549         return werror;
2550 }
2551
2552 /****************************************************************************
2553 ****************************************************************************/
2554
2555 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2556                                             TALLOC_CTX *mem_ctx,
2557                                             int argc, const char **argv)
2558 {
2559         WERROR result;
2560         NTSTATUS status;
2561         const char *printername;
2562         struct policy_handle pol = { 0, };
2563         union spoolss_PrinterInfo info;
2564         enum winreg_Type type;
2565         union spoolss_PrinterData data;
2566         DATA_BLOB blob;
2567         struct dcerpc_binding_handle *b = cli->binding_handle;
2568
2569         /* parse the command arguments */
2570         if (argc < 5) {
2571                 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2572                         " <value> <data>\n",
2573                         argv[0]);
2574                 return WERR_OK;
2575         }
2576
2577         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2578
2579         type = REG_NONE;
2580
2581         if (strequal(argv[2], "string")) {
2582                 type = REG_SZ;
2583         }
2584
2585         if (strequal(argv[2], "binary")) {
2586                 type = REG_BINARY;
2587         }
2588
2589         if (strequal(argv[2], "dword")) {
2590                 type = REG_DWORD;
2591         }
2592
2593         if (strequal(argv[2], "multistring")) {
2594                 type = REG_MULTI_SZ;
2595         }
2596
2597         if (type == REG_NONE) {
2598                 printf("Unknown data type: %s\n", argv[2]);
2599                 result =  WERR_INVALID_PARAM;
2600                 goto done;
2601         }
2602
2603         /* get a printer handle */
2604
2605         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2606                                                printername,
2607                                                SEC_FLAG_MAXIMUM_ALLOWED,
2608                                                &pol);
2609         if (!W_ERROR_IS_OK(result)) {
2610                 goto done;
2611         }
2612
2613         result = rpccli_spoolss_getprinter(cli, mem_ctx,
2614                                            &pol,
2615                                            0,
2616                                            0,
2617                                            &info);
2618         if (!W_ERROR_IS_OK(result)) {
2619                 goto done;
2620         }
2621
2622         printf("%s\n", current_timestring(mem_ctx, true));
2623         printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2624
2625         /* Set the printer data */
2626
2627         switch (type) {
2628         case REG_SZ:
2629                 data.string = talloc_strdup(mem_ctx, argv[4]);
2630                 W_ERROR_HAVE_NO_MEMORY(data.string);
2631                 break;
2632         case REG_DWORD:
2633                 data.value = strtoul(argv[4], NULL, 10);
2634                 break;
2635         case REG_BINARY:
2636                 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2637                 break;
2638         case REG_MULTI_SZ: {
2639                 int i, num_strings;
2640                 const char **strings = NULL;
2641
2642                 num_strings = 0;
2643
2644                 for (i=4; i<argc; i++) {
2645                         if (strcmp(argv[i], "NULL") == 0) {
2646                                 argv[i] = "";
2647                         }
2648                         if (!add_string_to_array(mem_ctx, argv[i],
2649                                                  &strings,
2650                                                  &num_strings)) {
2651                                 result = WERR_NOMEM;
2652                                 goto done;
2653                         }
2654                 }
2655                 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2656                 if (!data.string_array) {
2657                         result = WERR_NOMEM;
2658                         goto done;
2659                 }
2660                 for (i=0; i < num_strings; i++) {
2661                         data.string_array[i] = strings[i];
2662                 }
2663                 break;
2664                 }
2665         default:
2666                 printf("Unknown data type: %s\n", argv[2]);
2667                 result = WERR_INVALID_PARAM;
2668                 goto done;
2669         }
2670
2671         result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2672         if (!W_ERROR_IS_OK(result)) {
2673                 goto done;
2674         }
2675
2676         status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2677                                                &pol,
2678                                                argv[3], /* value_name */
2679                                                type,
2680                                                blob.data,
2681                                                blob.length,
2682                                                &result);
2683         if (!NT_STATUS_IS_OK(status)) {
2684                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2685                 result = ntstatus_to_werror(status);
2686                 goto done;
2687         }
2688         if (!W_ERROR_IS_OK(result)) {
2689                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2690                 goto done;
2691         }
2692         printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2693
2694         result = rpccli_spoolss_getprinter(cli, mem_ctx,
2695                                            &pol,
2696                                            0,
2697                                            0,
2698                                            &info);
2699         if (!W_ERROR_IS_OK(result)) {
2700                 goto done;
2701         }
2702
2703         printf("%s\n", current_timestring(mem_ctx, true));
2704         printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2705
2706 done:
2707         /* cleanup */
2708         if (is_valid_policy_hnd(&pol)) {
2709                 WERROR _result;
2710                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2711         }
2712
2713         return result;
2714 }
2715
2716 /****************************************************************************
2717 ****************************************************************************/
2718
2719 static void display_job_info1(struct spoolss_JobInfo1 *r)
2720 {
2721         printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2722                r->user_name, r->document_name, r->text_status, r->pages_printed,
2723                r->total_pages);
2724 }
2725
2726 /****************************************************************************
2727 ****************************************************************************/
2728
2729 static void display_job_info2(struct spoolss_JobInfo2 *r)
2730 {
2731         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2732                r->position, r->job_id,
2733                r->user_name, r->document_name, r->text_status, r->pages_printed,
2734                r->total_pages, r->size);
2735 }
2736
2737 /****************************************************************************
2738 ****************************************************************************/
2739
2740 static void display_job_info3(struct spoolss_JobInfo3 *r)
2741 {
2742         printf("jobid[%d], next_jobid[%d]\n",
2743                 r->job_id, r->next_job_id);
2744 }
2745
2746 /****************************************************************************
2747 ****************************************************************************/
2748
2749 static void display_job_info4(struct spoolss_JobInfo4 *r)
2750 {
2751         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2752                r->position, r->job_id,
2753                r->user_name, r->document_name, r->text_status, r->pages_printed,
2754                r->total_pages, r->size, r->size_high);
2755 }
2756
2757 /****************************************************************************
2758 ****************************************************************************/
2759
2760 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2761                                       TALLOC_CTX *mem_ctx, int argc,
2762                                       const char **argv)
2763 {
2764         WERROR result;
2765         uint32_t level = 1, count, i;
2766         const char *printername;
2767         struct policy_handle hnd;
2768         union spoolss_JobInfo *info;
2769         struct dcerpc_binding_handle *b = cli->binding_handle;
2770
2771         if (argc < 2 || argc > 3) {
2772                 printf("Usage: %s printername [level]\n", argv[0]);
2773                 return WERR_OK;
2774         }
2775
2776         if (argc == 3) {
2777                 level = atoi(argv[2]);
2778         }
2779
2780         /* Open printer handle */
2781
2782         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2783
2784         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2785                                                printername,
2786                                                SEC_FLAG_MAXIMUM_ALLOWED,
2787                                                &hnd);
2788         if (!W_ERROR_IS_OK(result))
2789                 goto done;
2790
2791         /* Enumerate ports */
2792
2793         result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2794                                          &hnd,
2795                                          0, /* firstjob */
2796                                          1000, /* numjobs */
2797                                          level,
2798                                          0,
2799                                          &count,
2800                                          &info);
2801         if (!W_ERROR_IS_OK(result)) {
2802                 goto done;
2803         }
2804
2805         for (i = 0; i < count; i++) {
2806                 switch (level) {
2807                 case 1:
2808                         display_job_info1(&info[i].info1);
2809                         break;
2810                 case 2:
2811                         display_job_info2(&info[i].info2);
2812                         break;
2813                 default:
2814                         d_printf("unknown info level %d\n", level);
2815                         break;
2816                 }
2817         }
2818
2819 done:
2820         if (is_valid_policy_hnd(&hnd)) {
2821                 WERROR _result;
2822                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2823         }
2824
2825         return result;
2826 }
2827
2828 /****************************************************************************
2829 ****************************************************************************/
2830
2831 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2832                                   TALLOC_CTX *mem_ctx, int argc,
2833                                   const char **argv)
2834 {
2835         WERROR result;
2836         const char *printername;
2837         struct policy_handle hnd;
2838         uint32_t job_id;
2839         uint32_t level = 1;
2840         union spoolss_JobInfo info;
2841         struct dcerpc_binding_handle *b = cli->binding_handle;
2842
2843         if (argc < 3 || argc > 4) {
2844                 printf("Usage: %s printername job_id [level]\n", argv[0]);
2845                 return WERR_OK;
2846         }
2847
2848         job_id = atoi(argv[2]);
2849
2850         if (argc == 4) {
2851                 level = atoi(argv[3]);
2852         }
2853
2854         /* Open printer handle */
2855
2856         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2857
2858         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2859                                                printername,
2860                                                SEC_FLAG_MAXIMUM_ALLOWED,
2861                                                &hnd);
2862         if (!W_ERROR_IS_OK(result)) {
2863                 goto done;
2864         }
2865
2866         /* Enumerate ports */
2867
2868         result = rpccli_spoolss_getjob(cli, mem_ctx,
2869                                        &hnd,
2870                                        job_id,
2871                                        level,
2872                                        0,
2873                                        &info);
2874
2875         if (!W_ERROR_IS_OK(result)) {
2876                 goto done;
2877         }
2878
2879         switch (level) {
2880         case 1:
2881                 display_job_info1(&info.info1);
2882                 break;
2883         case 2:
2884                 display_job_info2(&info.info2);
2885                 break;
2886         case 3:
2887                 display_job_info3(&info.info3);
2888                 break;
2889         case 4:
2890                 display_job_info4(&info.info4);
2891                 break;
2892         default:
2893                 d_printf("unknown info level %d\n", level);
2894                 break;
2895         }
2896
2897 done:
2898         if (is_valid_policy_hnd(&hnd)) {
2899                 WERROR _result;
2900                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2901         }
2902
2903         return result;
2904 }
2905
2906 /****************************************************************************
2907 ****************************************************************************/
2908
2909 static struct {
2910         const char *name;
2911         enum spoolss_JobControl val;
2912 } cmdvals[] = {
2913         {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2914         {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2915         {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2916         {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2917         {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2918         {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2919         {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2920         {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2921         {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2922 };
2923
2924 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2925 {
2926         int i;
2927
2928         for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2929                 if (strequal(cmdvals[i].name, cmd)) {
2930                         return cmdvals[i].val;
2931                 }
2932         }
2933         return (enum spoolss_JobControl)atoi(cmd);
2934 }
2935
2936 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2937                                   TALLOC_CTX *mem_ctx, int argc,
2938                                   const char **argv)
2939 {
2940         WERROR result;
2941         NTSTATUS status;
2942         const char *printername;
2943         struct policy_handle hnd;
2944         uint32_t job_id;
2945         enum spoolss_JobControl command;
2946         struct dcerpc_binding_handle *b = cli->binding_handle;
2947
2948         if (argc != 4) {
2949                 printf("Usage: %s printername job_id command\n", argv[0]);
2950                 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2951                         "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2952                 return WERR_OK;
2953         }
2954
2955         job_id = atoi(argv[2]);
2956         command = parse_setjob_command(argv[3]);
2957
2958         /* Open printer handle */
2959
2960         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2961
2962         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2963                                                printername,
2964                                                SEC_FLAG_MAXIMUM_ALLOWED,
2965                                                &hnd);
2966         if (!W_ERROR_IS_OK(result)) {
2967                 goto done;
2968         }
2969
2970         /* Set Job */
2971
2972         status = dcerpc_spoolss_SetJob(b, mem_ctx,
2973                                        &hnd,
2974                                        job_id,
2975                                        NULL,
2976                                        command,
2977                                        &result);
2978         if (!NT_STATUS_IS_OK(status)) {
2979                 result = ntstatus_to_werror(status);
2980                 goto done;
2981         }
2982         if (!W_ERROR_IS_OK(result)) {
2983                 goto done;
2984         }
2985
2986 done:
2987         if (is_valid_policy_hnd(&hnd)) {
2988                 WERROR _result;
2989                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2990         }
2991
2992         return result;
2993 }
2994
2995 /****************************************************************************
2996 ****************************************************************************/
2997
2998 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2999                                     TALLOC_CTX *mem_ctx, int argc,
3000                                     const char **argv)
3001 {
3002         WERROR result;
3003         NTSTATUS status;
3004         const char *printername;
3005         struct policy_handle hnd;
3006         uint32_t value_needed;
3007         enum winreg_Type type;
3008         uint32_t data_needed;
3009         struct dcerpc_binding_handle *b = cli->binding_handle;
3010         struct spoolss_EnumPrinterData r;
3011
3012         if (argc != 2) {
3013                 printf("Usage: %s printername\n", argv[0]);
3014                 return WERR_OK;
3015         }
3016
3017         /* Open printer handle */
3018
3019         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3020
3021         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3022                                                printername,
3023                                                SEC_FLAG_MAXIMUM_ALLOWED,
3024                                                &hnd);
3025         if (!W_ERROR_IS_OK(result)) {
3026                 goto done;
3027         }
3028
3029         /* Enumerate data */
3030
3031         r.in.handle = &hnd;
3032         r.in.enum_index = 0;
3033         r.in.value_offered = 0;
3034         r.in.data_offered = 0;
3035         r.out.value_name = NULL;
3036         r.out.value_needed = &value_needed;
3037         r.out.type = &type;
3038         r.out.data = NULL;
3039         r.out.data_needed = &data_needed;
3040
3041         status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3042         if (!NT_STATUS_IS_OK(status)) {
3043                 result = ntstatus_to_werror(status);
3044                 goto done;
3045         }
3046
3047         if (!W_ERROR_IS_OK(r.out.result)) {
3048                 result = r.out.result;
3049                 goto done;
3050         }
3051
3052         r.in.data_offered       = *r.out.data_needed;
3053         r.in.value_offered      = *r.out.value_needed;
3054         r.out.data              = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3055         r.out.value_name        = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3056
3057         do {
3058
3059                 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3060                 if (!NT_STATUS_IS_OK(status)) {
3061                         result = ntstatus_to_werror(status);
3062                         goto done;
3063                 }
3064
3065                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3066                         result = WERR_OK;
3067                         break;
3068                 }
3069
3070                 r.in.enum_index++;
3071
3072                 display_reg_value(r.out.value_name, *r.out.type,
3073                                   data_blob_const(r.out.data, r.in.data_offered));
3074
3075         } while (W_ERROR_IS_OK(r.out.result));
3076
3077 done:
3078         if (is_valid_policy_hnd(&hnd)) {
3079                 WERROR _result;
3080                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3081         }
3082
3083         return result;
3084 }
3085
3086 /****************************************************************************
3087 ****************************************************************************/
3088
3089 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3090                                           TALLOC_CTX *mem_ctx, int argc,
3091                                           const char **argv)
3092 {
3093         WERROR result;
3094         uint32_t i;
3095         const char *printername;
3096         struct policy_handle hnd;
3097         uint32_t count;
3098         struct spoolss_PrinterEnumValues *info;
3099         struct dcerpc_binding_handle *b = cli->binding_handle;
3100
3101         if (argc != 3) {
3102                 printf("Usage: %s printername <keyname>\n", argv[0]);
3103                 return WERR_OK;
3104         }
3105
3106         /* Open printer handle */
3107
3108         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3109
3110         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3111                                                printername,
3112                                                SEC_FLAG_MAXIMUM_ALLOWED,
3113                                                &hnd);
3114         if (!W_ERROR_IS_OK(result)) {
3115                 goto done;
3116         }
3117
3118         /* Enumerate subkeys */
3119
3120         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3121                                                   &hnd,
3122                                                   argv[2],
3123                                                   0,
3124                                                   &count,
3125                                                   &info);
3126         if (!W_ERROR_IS_OK(result)) {
3127                 goto done;
3128         }
3129
3130         for (i=0; i < count; i++) {
3131                 display_printer_data(info[i].value_name,
3132                                      info[i].type,
3133                                      info[i].data->data,
3134                                      info[i].data->length);
3135         }
3136
3137  done:
3138         if (is_valid_policy_hnd(&hnd)) {
3139                 WERROR _result;
3140                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3141         }
3142
3143         return result;
3144 }
3145
3146 /****************************************************************************
3147 ****************************************************************************/
3148
3149 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3150                                           TALLOC_CTX *mem_ctx, int argc,
3151                                           const char **argv)
3152 {
3153         WERROR result;
3154         const char *printername;
3155         const char *keyname = NULL;
3156         struct policy_handle hnd;
3157         const char **key_buffer = NULL;
3158         int i;
3159         uint32_t offered = 0;
3160         struct dcerpc_binding_handle *b = cli->binding_handle;
3161
3162         if (argc < 2 || argc > 4) {
3163                 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3164                 return WERR_OK;
3165         }
3166
3167         if (argc >= 3) {
3168                 keyname = argv[2];
3169         } else {
3170                 keyname = "";
3171         }
3172
3173         if (argc == 4) {
3174                 offered = atoi(argv[3]);
3175         }
3176
3177         /* Open printer handle */
3178
3179         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3180
3181         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3182                                                printername,
3183                                                SEC_FLAG_MAXIMUM_ALLOWED,
3184                                                &hnd);
3185         if (!W_ERROR_IS_OK(result)) {
3186                 goto done;
3187         }
3188
3189         /* Enumerate subkeys */
3190
3191         result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3192                                                &hnd,
3193                                                keyname,
3194                                                &key_buffer,
3195                                                offered);
3196
3197         if (!W_ERROR_IS_OK(result)) {
3198                 goto done;
3199         }
3200
3201         for (i=0; key_buffer && key_buffer[i]; i++) {
3202                 printf("%s\n", key_buffer[i]);
3203         }
3204
3205  done:
3206
3207         if (is_valid_policy_hnd(&hnd)) {
3208                 WERROR _result;
3209                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3210         }
3211
3212         return result;
3213 }
3214
3215 /****************************************************************************
3216 ****************************************************************************/
3217
3218 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3219                                      TALLOC_CTX *mem_ctx, int argc,
3220                                      const char **argv)
3221 {
3222         const char *printername;
3223         const char *clientname;
3224         struct policy_handle hnd = { 0, };
3225         WERROR result;
3226         NTSTATUS status;
3227         struct spoolss_NotifyOption option;
3228         struct dcerpc_binding_handle *b = cli->binding_handle;
3229
3230         if (argc != 2) {
3231                 printf("Usage: %s printername\n", argv[0]);
3232                 result = WERR_OK;
3233                 goto done;
3234         }
3235
3236         /* Open printer */
3237
3238         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3239
3240         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3241                                                printername,
3242                                                SEC_FLAG_MAXIMUM_ALLOWED,
3243                                                &hnd);
3244         if (!W_ERROR_IS_OK(result)) {
3245                 printf("Error opening %s\n", argv[1]);
3246                 goto done;
3247         }
3248
3249         /* Create spool options */
3250
3251         option.version = 2;
3252         option.count = 2;
3253
3254         option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3255         if (option.types == NULL) {
3256                 result = WERR_NOMEM;
3257                 goto done;
3258         }
3259
3260         option.types[0].type = PRINTER_NOTIFY_TYPE;
3261         option.types[0].count = 1;
3262         option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3263         if (option.types[0].fields == NULL) {
3264                 result = WERR_NOMEM;
3265                 goto done;
3266         }
3267         option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3268
3269         option.types[1].type = JOB_NOTIFY_TYPE;
3270         option.types[1].count = 1;
3271         option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3272         if (option.types[1].fields == NULL) {
3273                 result = WERR_NOMEM;
3274                 goto done;
3275         }
3276         option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3277
3278         clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3279         if (!clientname) {
3280                 result = WERR_NOMEM;
3281                 goto done;
3282         }
3283
3284         /* Send rffpcnex */
3285
3286         status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3287                                                                      &hnd,
3288                                                                      0,
3289                                                                      0,
3290                                                                      clientname,
3291                                                                      123,
3292                                                                      &option,
3293                                                                      &result);
3294         if (!NT_STATUS_IS_OK(status)) {
3295                 result = ntstatus_to_werror(status);
3296                 goto done;
3297         }
3298         if (!W_ERROR_IS_OK(result)) {
3299                 printf("Error rffpcnex %s\n", argv[1]);
3300                 goto done;
3301         }
3302
3303 done:
3304         if (is_valid_policy_hnd(&hnd)) {
3305                 WERROR _result;
3306                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3307         }
3308
3309         return result;
3310 }
3311
3312 /****************************************************************************
3313 ****************************************************************************/
3314
3315 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3316                              struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3317 {
3318         union spoolss_PrinterInfo info1, info2;
3319         WERROR werror;
3320         TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3321
3322         printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3323         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3324                                            hnd1,
3325                                            2,
3326                                            0,
3327                                            &info1);
3328         if ( !W_ERROR_IS_OK(werror) ) {
3329                 printf("failed (%s)\n", win_errstr(werror));
3330                 talloc_destroy(mem_ctx);
3331                 return false;
3332         }
3333         printf("ok\n");
3334
3335         printf("Retrieving printer properties for %s...", cli2->desthost);
3336         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3337                                            hnd2,
3338                                            2,
3339                                            0,
3340                                            &info2);
3341         if ( !W_ERROR_IS_OK(werror) ) {
3342                 printf("failed (%s)\n", win_errstr(werror));
3343                 talloc_destroy(mem_ctx);
3344                 return false;
3345         }
3346         printf("ok\n");
3347
3348         talloc_destroy(mem_ctx);
3349
3350         return true;
3351 }
3352
3353 /****************************************************************************
3354 ****************************************************************************/
3355
3356 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3357                                      struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3358 {
3359         union spoolss_PrinterInfo info1, info2;
3360         WERROR werror;
3361         TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3362         struct security_descriptor *sd1, *sd2;
3363         bool result = true;
3364
3365
3366         printf("Retrieving printer security for %s...", cli1->desthost);
3367         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3368                                            hnd1,
3369                                            3,
3370                                            0,
3371                                            &info1);
3372         if ( !W_ERROR_IS_OK(werror) ) {
3373                 printf("failed (%s)\n", win_errstr(werror));
3374                 result = false;
3375                 goto done;
3376         }
3377         printf("ok\n");
3378
3379         printf("Retrieving printer security for %s...", cli2->desthost);
3380         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3381                                            hnd2,
3382                                            3,
3383                                            0,
3384                                            &info2);
3385         if ( !W_ERROR_IS_OK(werror) ) {
3386                 printf("failed (%s)\n", win_errstr(werror));
3387                 result = false;
3388                 goto done;
3389         }
3390         printf("ok\n");
3391
3392
3393         printf("++ ");
3394
3395         sd1 = info1.info3.secdesc;
3396         sd2 = info2.info3.secdesc;
3397
3398         if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3399                 printf("NULL secdesc!\n");
3400                 result = false;
3401                 goto done;
3402         }
3403
3404         if (!security_descriptor_equal( sd1, sd2 ) ) {
3405                 printf("Security Descriptors *not* equal!\n");
3406                 result = false;
3407                 goto done;
3408         }
3409
3410         printf("Security descriptors match\n");
3411
3412 done:
3413         talloc_destroy(mem_ctx);
3414         return result;
3415 }
3416
3417
3418 /****************************************************************************
3419 ****************************************************************************/
3420
3421 extern struct user_auth_info *rpcclient_auth_info;
3422
3423 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3424                                      TALLOC_CTX *mem_ctx, int argc,
3425                                      const char **argv)
3426 {
3427         const char *printername;
3428         char *printername_path = NULL;
3429         struct cli_state *cli_server2 = NULL;
3430         struct rpc_pipe_client *cli2 = NULL;
3431         struct policy_handle hPrinter1, hPrinter2;
3432         NTSTATUS nt_status;
3433         WERROR werror;
3434
3435         if ( argc != 3 )  {
3436                 printf("Usage: %s <printer> <server>\n", argv[0]);
3437                 return WERR_OK;
3438         }
3439
3440         printername = argv[1];
3441
3442         /* first get the connection to the remote server */
3443
3444         nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
3445                                         NULL, 0,
3446                                         "IPC$", "IPC",
3447                                         get_cmdline_auth_info_username(rpcclient_auth_info),
3448                                         lp_workgroup(),
3449                                         get_cmdline_auth_info_password(rpcclient_auth_info),
3450                                         get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3451                                         get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3452
3453         if ( !NT_STATUS_IS_OK(nt_status) )
3454                 return WERR_GENERAL_FAILURE;
3455
3456         nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3457                                              &cli2);
3458         if (!NT_STATUS_IS_OK(nt_status)) {
3459                 printf("failed to open spoolss pipe on server %s (%s)\n",
3460                         argv[2], nt_errstr(nt_status));
3461                 return WERR_GENERAL_FAILURE;
3462         }
3463
3464         /* now open up both printers */
3465
3466         RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3467
3468         printf("Opening %s...", printername_path);
3469
3470         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3471                                                printername_path,
3472                                                PRINTER_ALL_ACCESS,
3473                                                &hPrinter1);
3474         if ( !W_ERROR_IS_OK(werror) ) {
3475                 printf("failed (%s)\n", win_errstr(werror));
3476                 goto done;
3477         }
3478         printf("ok\n");
3479
3480         RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3481
3482         printf("Opening %s...", printername_path);
3483         werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3484                                                printername_path,
3485                                                PRINTER_ALL_ACCESS,
3486                                                &hPrinter2);
3487         if ( !W_ERROR_IS_OK(werror) ) {
3488                  printf("failed (%s)\n", win_errstr(werror));
3489                 goto done;
3490         }
3491         printf("ok\n");
3492
3493         compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3494         compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3495 #if 0
3496         compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3497 #endif
3498
3499
3500 done:
3501         /* cleanup */
3502
3503         printf("Closing printers...");
3504         {
3505                 WERROR _result;
3506                 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3507                 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3508         }
3509         printf("ok\n");
3510
3511         /* close the second remote connection */
3512
3513         cli_shutdown( cli_server2 );
3514         return WERR_OK;
3515 }
3516
3517 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3518 {
3519         printf("print_processor_name: %s\n", r->print_processor_name);
3520 }
3521
3522 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3523                                      TALLOC_CTX *mem_ctx, int argc,
3524                                      const char **argv)
3525 {
3526         WERROR werror;
3527         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3528         uint32_t num_procs, level = 1, i;
3529         union spoolss_PrintProcessorInfo *procs;
3530
3531         /* Parse the command arguments */
3532
3533         if (argc < 1 || argc > 4) {
3534                 printf ("Usage: %s [environment] [level]\n", argv[0]);
3535                 return WERR_OK;
3536         }
3537
3538         if (argc >= 2) {
3539                 environment = argv[1];
3540         }
3541
3542         if (argc == 3) {
3543                 level = atoi(argv[2]);
3544         }
3545
3546         /* Enumerate Print Processors */
3547
3548         werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3549                                                     cli->srv_name_slash,
3550                                                     environment,
3551                                                     level,
3552                                                     0,
3553                                                     &num_procs,
3554                                                     &procs);
3555         if (!W_ERROR_IS_OK(werror))
3556                 goto done;
3557
3558         /* Display output */
3559
3560         for (i = 0; i < num_procs; i++) {
3561                 switch (level) {
3562                 case 1:
3563                         display_proc_info1(&procs[i].info1);
3564                         break;
3565                 }
3566         }
3567
3568  done:
3569         return werror;
3570 }
3571
3572 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3573 {
3574         printf("name_array: %s\n", r->name_array);
3575 }
3576
3577 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3578                                                TALLOC_CTX *mem_ctx, int argc,
3579                                                const char **argv)
3580 {
3581         WERROR werror;
3582         const char *print_processor_name = "winprint";
3583         uint32_t num_procs, level = 1, i;
3584         union spoolss_PrintProcDataTypesInfo *procs;
3585
3586         /* Parse the command arguments */
3587
3588         if (argc < 1 || argc > 4) {
3589                 printf ("Usage: %s [environment] [level]\n", argv[0]);
3590                 return WERR_OK;
3591         }
3592
3593         if (argc >= 2) {
3594                 print_processor_name = argv[1];
3595         }
3596
3597         if (argc == 3) {
3598                 level = atoi(argv[2]);
3599         }
3600
3601         /* Enumerate Print Processor Data Types */
3602
3603         werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3604                                                             cli->srv_name_slash,
3605                                                             print_processor_name,
3606                                                             level,
3607                                                             0,
3608                                                             &num_procs,
3609                                                             &procs);
3610         if (!W_ERROR_IS_OK(werror))
3611                 goto done;
3612
3613         /* Display output */
3614
3615         for (i = 0; i < num_procs; i++) {
3616                 switch (level) {
3617                 case 1:
3618                         display_proc_data_types_info1(&procs[i].info1);
3619                         break;
3620                 }
3621         }
3622
3623  done:
3624         return werror;
3625 }
3626
3627 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3628 {
3629         printf("monitor_name: %s\n", r->monitor_name);
3630 }
3631
3632 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3633 {
3634         printf("monitor_name: %s\n", r->monitor_name);
3635         printf("environment: %s\n", r->environment);
3636         printf("dll_name: %s\n", r->dll_name);
3637 }
3638
3639 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3640                                         TALLOC_CTX *mem_ctx, int argc,
3641                                         const char **argv)
3642 {
3643         WERROR werror;
3644         uint32_t count, level = 1, i;
3645         union spoolss_MonitorInfo *info;
3646
3647         /* Parse the command arguments */
3648
3649         if (argc > 2) {
3650                 printf("Usage: %s [level]\n", argv[0]);
3651                 return WERR_OK;
3652         }
3653
3654         if (argc == 2) {
3655                 level = atoi(argv[1]);
3656         }
3657
3658         /* Enumerate Print Monitors */
3659
3660         werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3661                                              cli->srv_name_slash,
3662                                              level,
3663                                              0,
3664                                              &count,
3665                                              &info);
3666         if (!W_ERROR_IS_OK(werror)) {
3667                 goto done;
3668         }
3669
3670         /* Display output */
3671
3672         for (i = 0; i < count; i++) {
3673                 switch (level) {
3674                 case 1:
3675                         display_monitor1(&info[i].info1);
3676                         break;
3677                 case 2:
3678                         display_monitor2(&info[i].info2);
3679                         break;
3680                 }
3681         }
3682
3683  done:
3684         return werror;
3685 }
3686
3687 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3688                                             TALLOC_CTX *mem_ctx, int argc,
3689                                             const char **argv)
3690 {
3691         WERROR result;
3692         NTSTATUS status;
3693         struct policy_handle handle, gdi_handle;
3694         const char *printername;
3695         struct spoolss_DevmodeContainer devmode_ctr;
3696         struct dcerpc_binding_handle *b = cli->binding_handle;
3697
3698         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3699
3700         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3701                                                printername,
3702                                                SEC_FLAG_MAXIMUM_ALLOWED,
3703                                                &handle);
3704         if (!W_ERROR_IS_OK(result)) {
3705                 return result;
3706         }
3707
3708         ZERO_STRUCT(devmode_ctr);
3709
3710         status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3711                                                 &handle,
3712                                                 &gdi_handle,
3713                                                 &devmode_ctr,
3714                                                 &result);
3715         if (!NT_STATUS_IS_OK(status)) {
3716                 result = ntstatus_to_werror(status);
3717                 goto done;
3718         }
3719         if (!W_ERROR_IS_OK(result)) {
3720                 goto done;
3721         }
3722
3723  done:
3724         if (is_valid_policy_hnd(&gdi_handle)) {
3725                 WERROR _result;
3726                 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3727         }
3728         if (is_valid_policy_hnd(&handle)) {
3729                 WERROR _result;
3730                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3731         }
3732
3733         return result;
3734 }
3735
3736 static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3737                                                         TALLOC_CTX *mem_ctx, int argc,
3738                                                         const char **argv)
3739 {
3740         WERROR result;
3741         NTSTATUS status;
3742         struct policy_handle handle, gdi_handle;
3743         const char *printername;
3744         struct spoolss_DevmodeContainer devmode_ctr;
3745         struct dcerpc_binding_handle *b = cli->binding_handle;
3746         DATA_BLOB in,out;
3747         uint32_t count = 0;
3748
3749         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3750
3751         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3752                                                printername,
3753                                                SEC_FLAG_MAXIMUM_ALLOWED,
3754                                                &handle);
3755         if (!W_ERROR_IS_OK(result)) {
3756                 return result;
3757         }
3758
3759         ZERO_STRUCT(devmode_ctr);
3760
3761         status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3762                                                 &handle,
3763                                                 &gdi_handle,
3764                                                 &devmode_ctr,
3765                                                 &result);
3766         if (!NT_STATUS_IS_OK(status)) {
3767                 result = ntstatus_to_werror(status);
3768                 goto done;
3769         }
3770         if (!W_ERROR_IS_OK(result)) {
3771                 goto done;
3772         }
3773
3774         in = data_blob_string_const("");
3775         out = data_blob_talloc_zero(mem_ctx, 4);
3776
3777         status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3778                                                          &gdi_handle,
3779                                                          in.data,
3780                                                          in.length,
3781                                                          out.data,
3782                                                          out.length,
3783                                                          0, /* ul */
3784                                                          &result);
3785         if (!NT_STATUS_IS_OK(status)) {
3786                 result = ntstatus_to_werror(status);
3787                 goto done;
3788         }
3789         if (!W_ERROR_IS_OK(result)) {
3790                 goto done;
3791         }
3792
3793         count = IVAL(out.data, 0);
3794
3795         out = data_blob_talloc_zero(mem_ctx,
3796                                     count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3797
3798         status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3799                                                          &gdi_handle,
3800                                                          in.data,
3801                                                          in.length,
3802                                                          out.data,
3803                                                          out.length,
3804                                                          0, /* ul */
3805                                                          &result);
3806         if (!NT_STATUS_IS_OK(status)) {
3807                 result = ntstatus_to_werror(status);
3808                 goto done;
3809         }
3810         if (!W_ERROR_IS_OK(result)) {
3811                 goto done;
3812         }
3813
3814         {
3815                 enum ndr_err_code ndr_err;
3816                 struct UNIVERSAL_FONT_ID_ctr r;
3817
3818                 ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3819                         (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3820                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3821                         NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3822                 }
3823         }
3824
3825  done:
3826         if (is_valid_policy_hnd(&gdi_handle)) {
3827                 WERROR _result;
3828                 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3829         }
3830         if (is_valid_policy_hnd(&handle)) {
3831                 WERROR _result;
3832                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3833         }
3834
3835         return result;
3836 }
3837
3838 /* List of commands exported by this module */
3839 struct cmd_set spoolss_commands[] = {
3840
3841         { "SPOOLSS"  },
3842
3843         { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &ndr_table_spoolss, NULL, "Add a print driver",                  "" },
3844         { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &ndr_table_spoolss, NULL, "Add a printer",                       "" },
3845         { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &ndr_table_spoolss, NULL, "Delete a printer driver",             "" },
3846         { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &ndr_table_spoolss, NULL, "Delete a printer driver with files",  "" },
3847         { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &ndr_table_spoolss, NULL, "Enumerate printer data",              "" },
3848         { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &ndr_table_spoolss, NULL, "Enumerate printer data for a key",    "" },
3849         { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &ndr_table_spoolss, NULL, "Enumerate printer keys",              "" },
3850         { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &ndr_table_spoolss, NULL, "Enumerate print jobs",                "" },
3851         { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &ndr_table_spoolss, NULL, "Get print job",                       "" },
3852         { "setjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job,            &ndr_table_spoolss, NULL, "Set print job",                       "" },
3853         { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &ndr_table_spoolss, NULL, "Enumerate printer ports",             "" },
3854         { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &ndr_table_spoolss, NULL, "Enumerate installed printer drivers", "" },
3855         { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &ndr_table_spoolss, NULL, "Enumerate printers",                  "" },
3856         { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &ndr_table_spoolss, NULL, "Get print driver data",               "" },
3857         { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &ndr_table_spoolss, NULL, "Get printer driver data with keyname", ""},
3858         { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &ndr_table_spoolss, NULL, "Get print driver information",        "" },
3859         { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &ndr_table_spoolss, NULL, "Get print driver upload directory",   "" },
3860         { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &ndr_table_spoolss, NULL, "Get printer info",                    "" },
3861         { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer,       &ndr_table_spoolss, NULL, "Open printer handle",                 "" },
3862         { "openprinter_ex",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &ndr_table_spoolss, NULL, "Open printer handle",                 "" },
3863         { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &ndr_table_spoolss, NULL, "Set printer driver",                  "" },
3864         { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &ndr_table_spoolss, NULL, "Get print processor directory",       "" },
3865         { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &ndr_table_spoolss, NULL, "Add form",                            "" },
3866         { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &ndr_table_spoolss, NULL, "Set form",                            "" },
3867         { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &ndr_table_spoolss, NULL, "Get form",                            "" },
3868         { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &ndr_table_spoolss, NULL, "Delete form",                         "" },
3869         { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &ndr_table_spoolss, NULL, "Enumerate forms",                     "" },
3870         { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &ndr_table_spoolss, NULL, "Set printer comment",                 "" },
3871         { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &ndr_table_spoolss, NULL, "Set printername",                 "" },
3872         { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &ndr_table_spoolss, NULL, "Set REG_SZ printer data",             "" },
3873         { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &ndr_table_spoolss, NULL, "Rffpcnex test", "" },
3874         { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &ndr_table_spoolss, NULL, "Printer comparison test", "" },
3875         { "enumprocs",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs,         &ndr_table_spoolss, NULL, "Enumerate Print Processors",          "" },
3876         { "enumprocdatatypes",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3877         { "enummonitors",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors,      &ndr_table_spoolss, NULL, "Enumerate Print Monitors", "" },
3878         { "createprinteric",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic,  &ndr_table_spoolss, NULL, "Create Printer IC", "" },
3879         { "playgdiscriptonprinteric",   RPC_RTYPE_WERROR, NULL, cmd_spoolss_play_gdi_script_on_printer_ic,  &ndr_table_spoolss, NULL, "Create Printer IC", "" },
3880
3881         { NULL }
3882 };