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