libcli/security: move display_sec headers to own header file and add to
[kai/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 "rpc_client/cli_pipe.h"
28 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "rpc_client/cli_spoolss.h"
30 #include "rpc_client/init_spoolss.h"
31 #include "registry.h"
32 #include "registry/reg_objects.h"
33 #include "nt_printing.h"
34 #include "../libcli/security/display_sec.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(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(struct regval_blob *value)
767 {
768         const char *text = NULL;
769         DATA_BLOB blob;
770
771         switch(regval_type(value)) {
772         case REG_DWORD:
773                 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
774                        *((uint32_t *) regval_data_p(value)));
775                 break;
776         case REG_SZ:
777                 blob = data_blob_const(regval_data_p(value), regval_size(value));
778                 pull_reg_sz(talloc_tos(), &blob, &text);
779                 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
780                 break;
781         case REG_BINARY: {
782                 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
783                 size_t i, len;
784                 printf("%s: REG_BINARY:", regval_name(value));
785                 len = strlen(hex);
786                 for (i=0; i<len; i++) {
787                         if (hex[i] == '\0') {
788                                 break;
789                         }
790                         if (i%40 == 0) {
791                                 putchar('\n');
792                         }
793                         putchar(hex[i]);
794                 }
795                 TALLOC_FREE(hex);
796                 putchar('\n');
797                 break;
798         }
799         case REG_MULTI_SZ: {
800                 uint32_t i;
801                 const char **values;
802                 blob = data_blob_const(regval_data_p(value), regval_size(value));
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", regval_name(value));
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", regval_name(value), regval_type(value));
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(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 Printer 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                 add_string_to_array(deps, str, &file_array, &count);
1676                 str = strtok_r(NULL, ",", &saveptr);
1677         }
1678
1679         deps->string = talloc_zero_array(deps, const char *, count + 1);
1680         if (!deps->string) {
1681                 return false;
1682         }
1683
1684         for (i=0; i < count; i++) {
1685                 deps->string[i] = file_array[i];
1686         }
1687
1688         r->dependent_files = deps;
1689
1690         return true;
1691 }
1692
1693 /****************************************************************************
1694 ****************************************************************************/
1695
1696 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1697                                              TALLOC_CTX *mem_ctx,
1698                                              int argc, const char **argv)
1699 {
1700         WERROR result;
1701         NTSTATUS status;
1702         uint32_t                  level = 3;
1703         struct spoolss_AddDriverInfoCtr info_ctr;
1704         struct spoolss_AddDriverInfo3 info3;
1705         const char              *arch;
1706         char                    *driver_args;
1707         struct dcerpc_binding_handle *b = cli->binding_handle;
1708
1709         /* parse the command arguments */
1710         if (argc != 3 && argc != 4)
1711         {
1712                 printf ("Usage: %s <Environment> \\\n", argv[0]);
1713                 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1714                 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1715                 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1716                 printf ("\t[version]\n");
1717
1718             return WERR_OK;
1719         }
1720
1721         /* Fill in the spoolss_AddDriverInfo3 struct */
1722         ZERO_STRUCT(info3);
1723
1724         arch = cmd_spoolss_get_short_archi(argv[1]);
1725         if (!arch) {
1726                 printf ("Error Unknown architecture [%s]\n", argv[1]);
1727                 return WERR_INVALID_PARAM;
1728         }
1729
1730         set_drv_info_3_env(mem_ctx, &info3, arch);
1731
1732         driver_args = talloc_strdup( mem_ctx, argv[2] );
1733         if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1734         {
1735                 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1736                 return WERR_INVALID_PARAM;
1737         }
1738
1739         /* if printer driver version specified, override the default version
1740          * used by the architecture.  This allows installation of Windows
1741          * 2000 (version 3) printer drivers. */
1742         if (argc == 4)
1743         {
1744                 info3.version = atoi(argv[3]);
1745         }
1746
1747
1748         info_ctr.level          = level;
1749         info_ctr.info.info3     = &info3;
1750
1751         status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1752                                                  cli->srv_name_slash,
1753                                                  &info_ctr,
1754                                                  &result);
1755         if (!NT_STATUS_IS_OK(status)) {
1756                 return ntstatus_to_werror(status);
1757         }
1758         if (W_ERROR_IS_OK(result)) {
1759                 printf ("Printer Driver %s successfully installed.\n",
1760                         info3.driver_name);
1761         }
1762
1763         return result;
1764 }
1765
1766
1767 /****************************************************************************
1768 ****************************************************************************/
1769
1770 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1771                                          TALLOC_CTX *mem_ctx,
1772                                          int argc, const char **argv)
1773 {
1774         WERROR result;
1775         struct spoolss_SetPrinterInfoCtr info_ctr;
1776         struct spoolss_SetPrinterInfo2 info2;
1777
1778         /* parse the command arguments */
1779         if (argc != 5)
1780         {
1781                 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1782                 return WERR_OK;
1783         }
1784
1785         /* Fill in the DRIVER_INFO_2 struct */
1786         ZERO_STRUCT(info2);
1787
1788         info2.printername       = argv[1];
1789         info2.drivername        = argv[3];
1790         info2.sharename         = argv[2];
1791         info2.portname          = argv[4];
1792         info2.comment           = "Created by rpcclient";
1793         info2.printprocessor    = "winprint";
1794         info2.datatype          = "RAW";
1795         info2.devmode_ptr       = 0;
1796         info2.secdesc_ptr       = 0;
1797         info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
1798         info2.priority          = 0;
1799         info2.defaultpriority   = 0;
1800         info2.starttime         = 0;
1801         info2.untiltime         = 0;
1802
1803         /* These three fields must not be used by AddPrinter()
1804            as defined in the MS Platform SDK documentation..
1805            --jerry
1806         info2.status            = 0;
1807         info2.cjobs             = 0;
1808         info2.averageppm        = 0;
1809         */
1810
1811         info_ctr.level = 2;
1812         info_ctr.info.info2 = &info2;
1813
1814         result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1815                                              &info_ctr);
1816         if (W_ERROR_IS_OK(result))
1817                 printf ("Printer %s successfully installed.\n", argv[1]);
1818
1819         return result;
1820 }
1821
1822 /****************************************************************************
1823 ****************************************************************************/
1824
1825 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1826                                       TALLOC_CTX *mem_ctx,
1827                                       int argc, const char **argv)
1828 {
1829         struct policy_handle    pol;
1830         WERROR                  result;
1831         NTSTATUS                status;
1832         uint32_t                level = 2;
1833         const char              *printername;
1834         union spoolss_PrinterInfo info;
1835         struct spoolss_SetPrinterInfoCtr info_ctr;
1836         struct spoolss_SetPrinterInfo2 info2;
1837         struct spoolss_DevmodeContainer devmode_ctr;
1838         struct sec_desc_buf secdesc_ctr;
1839         struct dcerpc_binding_handle *b = cli->binding_handle;
1840
1841         ZERO_STRUCT(devmode_ctr);
1842         ZERO_STRUCT(secdesc_ctr);
1843
1844         /* parse the command arguments */
1845         if (argc != 3)
1846         {
1847                 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1848                 return WERR_OK;
1849         }
1850
1851         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1852
1853         /* Get a printer handle */
1854
1855         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1856                                                printername,
1857                                                PRINTER_ALL_ACCESS,
1858                                                &pol);
1859         if (!W_ERROR_IS_OK(result))
1860                 goto done;
1861
1862         /* Get printer info */
1863
1864         result = rpccli_spoolss_getprinter(cli, mem_ctx,
1865                                            &pol,
1866                                            level,
1867                                            0,
1868                                            &info);
1869         if (!W_ERROR_IS_OK(result)) {
1870                 printf ("Unable to retrieve printer information!\n");
1871                 goto done;
1872         }
1873
1874         /* Set the printer driver */
1875
1876         spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1877         info2.drivername = argv[2];
1878
1879         info_ctr.level = 2;
1880         info_ctr.info.info2 = &info2;
1881
1882         status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1883                                            &pol,
1884                                            &info_ctr,
1885                                            &devmode_ctr,
1886                                            &secdesc_ctr,
1887                                            0, /* command */
1888                                            &result);
1889         if (!NT_STATUS_IS_OK(status)) {
1890                 result = ntstatus_to_werror(status);
1891                 goto done;
1892         }
1893         if (!W_ERROR_IS_OK(result)) {
1894                 printf("SetPrinter call failed!\n");
1895                 goto done;
1896         }
1897
1898         printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1899
1900 done:
1901         /* Cleanup */
1902
1903         if (is_valid_policy_hnd(&pol)) {
1904                 WERROR _result;
1905                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1906         }
1907
1908         return result;
1909 }
1910
1911
1912 /****************************************************************************
1913 ****************************************************************************/
1914
1915 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1916                                          TALLOC_CTX *mem_ctx,
1917                                          int argc, const char **argv)
1918 {
1919         WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1920         NTSTATUS status;
1921         struct dcerpc_binding_handle *b = cli->binding_handle;
1922
1923         int   i;
1924         int vers = -1;
1925
1926         const char *arch = NULL;
1927         uint32_t delete_flags = 0;
1928
1929         /* parse the command arguments */
1930         if (argc < 2 || argc > 4) {
1931                 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1932                 return WERR_OK;
1933         }
1934
1935         if (argc >= 3)
1936                 arch = argv[2];
1937         if (argc == 4)
1938                 vers = atoi (argv[3]);
1939
1940         if (vers >= 0) {
1941                 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1942         }
1943
1944         /* delete the driver for all architectures */
1945         for (i=0; archi_table[i].long_archi; i++) {
1946
1947                 if (arch &&  !strequal( archi_table[i].long_archi, arch))
1948                         continue;
1949
1950                 if (vers >= 0 && archi_table[i].version != vers)
1951                         continue;
1952
1953                 /* make the call to remove the driver */
1954                 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1955                                                               cli->srv_name_slash,
1956                                                               archi_table[i].long_archi,
1957                                                               argv[1],
1958                                                               delete_flags,
1959                                                               archi_table[i].version,
1960                                                               &result);
1961                 if (!NT_STATUS_IS_OK(status)) {
1962                         return ntstatus_to_werror(status);
1963                 }
1964                 if ( !W_ERROR_IS_OK(result) )
1965                 {
1966                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1967                                 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1968                                         argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1969                         }
1970                 }
1971                 else
1972                 {
1973                         printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1974                         archi_table[i].long_archi, archi_table[i].version);
1975                         ret = WERR_OK;
1976                 }
1977         }
1978
1979         return ret;
1980 }
1981
1982
1983 /****************************************************************************
1984 ****************************************************************************/
1985
1986 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1987                                          TALLOC_CTX *mem_ctx,
1988                                          int argc, const char **argv)
1989 {
1990         WERROR result = WERR_OK;
1991         NTSTATUS status;
1992         int                     i;
1993         struct dcerpc_binding_handle *b = cli->binding_handle;
1994
1995         /* parse the command arguments */
1996         if (argc != 2) {
1997                 printf ("Usage: %s <driver>\n", argv[0]);
1998                 return WERR_OK;
1999         }
2000
2001         /* delete the driver for all architectures */
2002         for (i=0; archi_table[i].long_archi; i++) {
2003                 result = WERR_OK;
2004
2005                 /* make the call to remove the driver */
2006                 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2007                                                             cli->srv_name_slash,
2008                                                             archi_table[i].long_archi,
2009                                                             argv[1],
2010                                                             &result);
2011                 if (!NT_STATUS_IS_OK(status)) {
2012                         result = ntstatus_to_werror(status);
2013                         continue;
2014                 }
2015                 if ( !W_ERROR_IS_OK(result) ) {
2016                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2017                                 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2018                                         argv[1], archi_table[i].long_archi,
2019                                         win_errstr(result));
2020                         }
2021                 } else {
2022                         printf ("Driver %s removed for arch [%s].\n", argv[1],
2023                                 archi_table[i].long_archi);
2024                 }
2025         }
2026
2027         return result;
2028 }
2029
2030 /****************************************************************************
2031 ****************************************************************************/
2032
2033 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2034                                             TALLOC_CTX *mem_ctx,
2035                                             int argc, const char **argv)
2036 {
2037         WERROR result;
2038         NTSTATUS status;
2039         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2040         DATA_BLOB buffer;
2041         uint32_t offered;
2042         union spoolss_PrintProcessorDirectoryInfo info;
2043         uint32_t needed;
2044         struct dcerpc_binding_handle *b = cli->binding_handle;
2045
2046         /* parse the command arguments */
2047         if (argc > 2) {
2048                 printf ("Usage: %s [environment]\n", argv[0]);
2049                 return WERR_OK;
2050         }
2051
2052         if (argc == 2) {
2053                 environment = argv[1];
2054         }
2055
2056         status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2057                                                            cli->srv_name_slash,
2058                                                            environment,
2059                                                            1,
2060                                                            NULL, /* buffer */
2061                                                            0, /* offered */
2062                                                            NULL, /* info */
2063                                                            &needed,
2064                                                            &result);
2065         if (!NT_STATUS_IS_OK(status)) {
2066                 return ntstatus_to_werror(status);
2067         }
2068         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2069                 offered = needed;
2070                 buffer = data_blob_talloc_zero(mem_ctx, needed);
2071
2072                 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2073                                                                    cli->srv_name_slash,
2074                                                                    environment,
2075                                                                    1,
2076                                                                    &buffer,
2077                                                                    offered,
2078                                                                    &info,
2079                                                                    &needed,
2080                                                                    &result);
2081                 if (!NT_STATUS_IS_OK(status)) {
2082                         return ntstatus_to_werror(status);
2083                 }
2084         }
2085
2086         if (W_ERROR_IS_OK(result)) {
2087                 printf("%s\n", info.info1.directory_name);
2088         }
2089
2090         return result;
2091 }
2092
2093 /****************************************************************************
2094 ****************************************************************************/
2095
2096 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2097                                     int argc, const char **argv)
2098 {
2099         struct policy_handle handle;
2100         WERROR werror;
2101         NTSTATUS status;
2102         const char *printername;
2103         union spoolss_AddFormInfo info;
2104         struct spoolss_AddFormInfo1 info1;
2105         struct spoolss_AddFormInfo2 info2;
2106         uint32_t level = 1;
2107         struct dcerpc_binding_handle *b = cli->binding_handle;
2108
2109         /* Parse the command arguments */
2110
2111         if (argc < 3 || argc > 5) {
2112                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2113                 return WERR_OK;
2114         }
2115
2116         /* Get a printer handle */
2117
2118         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2119
2120         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2121                                                printername,
2122                                                PRINTER_ALL_ACCESS,
2123                                                &handle);
2124         if (!W_ERROR_IS_OK(werror))
2125                 goto done;
2126
2127         /* Dummy up some values for the form data */
2128
2129         if (argc == 4) {
2130                 level = atoi(argv[3]);
2131         }
2132
2133         switch (level) {
2134         case 1:
2135                 info1.flags             = SPOOLSS_FORM_USER;
2136                 info1.form_name         = argv[2];
2137                 info1.size.width        = 100;
2138                 info1.size.height       = 100;
2139                 info1.area.left         = 0;
2140                 info1.area.top          = 10;
2141                 info1.area.right        = 20;
2142                 info1.area.bottom       = 30;
2143
2144                 info.info1 = &info1;
2145
2146                 break;
2147         case 2:
2148                 info2.flags             = SPOOLSS_FORM_USER;
2149                 info2.form_name         = argv[2];
2150                 info2.size.width        = 100;
2151                 info2.size.height       = 100;
2152                 info2.area.left         = 0;
2153                 info2.area.top          = 10;
2154                 info2.area.right        = 20;
2155                 info2.area.bottom       = 30;
2156                 info2.keyword           = argv[2];
2157                 info2.string_type       = SPOOLSS_FORM_STRING_TYPE_NONE;
2158                 info2.mui_dll           = NULL;
2159                 info2.ressource_id      = 0;
2160                 info2.display_name      = argv[2];
2161                 info2.lang_id           = 0;
2162
2163                 info.info2 = &info2;
2164
2165                 break;
2166         default:
2167                 werror = WERR_INVALID_PARAM;
2168                 goto done;
2169         }
2170
2171         /* Add the form */
2172
2173
2174         status = dcerpc_spoolss_AddForm(b, mem_ctx,
2175                                         &handle,
2176                                         level,
2177                                         info,
2178                                         &werror);
2179         if (!NT_STATUS_IS_OK(status)) {
2180                 werror = ntstatus_to_werror(status);
2181                 goto done;
2182         }
2183  done:
2184         if (is_valid_policy_hnd(&handle)) {
2185                 WERROR _result;
2186                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2187         }
2188
2189         return werror;
2190 }
2191
2192 /****************************************************************************
2193 ****************************************************************************/
2194
2195 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2196                                     int argc, const char **argv)
2197 {
2198         struct policy_handle handle;
2199         WERROR werror;
2200         NTSTATUS status;
2201         const char *printername;
2202         union spoolss_AddFormInfo info;
2203         struct spoolss_AddFormInfo1 info1;
2204         struct dcerpc_binding_handle *b = cli->binding_handle;
2205
2206         /* Parse the command arguments */
2207
2208         if (argc != 3) {
2209                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2210                 return WERR_OK;
2211         }
2212
2213         /* Get a printer handle */
2214
2215         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2216
2217         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2218                                                printername,
2219                                                SEC_FLAG_MAXIMUM_ALLOWED,
2220                                                &handle);
2221         if (!W_ERROR_IS_OK(werror))
2222                 goto done;
2223
2224         /* Dummy up some values for the form data */
2225
2226         info1.flags             = SPOOLSS_FORM_PRINTER;
2227         info1.size.width        = 100;
2228         info1.size.height       = 100;
2229         info1.area.left         = 0;
2230         info1.area.top          = 1000;
2231         info1.area.right        = 2000;
2232         info1.area.bottom       = 3000;
2233         info1.form_name         = argv[2];
2234
2235         info.info1 = &info1;
2236
2237         /* Set the form */
2238
2239         status = dcerpc_spoolss_SetForm(b, mem_ctx,
2240                                         &handle,
2241                                         argv[2],
2242                                         1,
2243                                         info,
2244                                         &werror);
2245         if (!NT_STATUS_IS_OK(status)) {
2246                 werror = ntstatus_to_werror(status);
2247                 goto done;
2248         }
2249  done:
2250         if (is_valid_policy_hnd(&handle)) {
2251                 WERROR _result;
2252                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2253         }
2254
2255         return werror;
2256 }
2257
2258 /****************************************************************************
2259 ****************************************************************************/
2260
2261 static const char *get_form_flag(int form_flag)
2262 {
2263         switch (form_flag) {
2264         case SPOOLSS_FORM_USER:
2265                 return "FORM_USER";
2266         case SPOOLSS_FORM_BUILTIN:
2267                 return "FORM_BUILTIN";
2268         case SPOOLSS_FORM_PRINTER:
2269                 return "FORM_PRINTER";
2270         default:
2271                 return "unknown";
2272         }
2273 }
2274
2275 /****************************************************************************
2276 ****************************************************************************/
2277
2278 static void display_form_info1(struct spoolss_FormInfo1 *r)
2279 {
2280         printf("%s\n" \
2281                 "\tflag: %s (%d)\n" \
2282                 "\twidth: %d, length: %d\n" \
2283                 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2284                 r->form_name, get_form_flag(r->flags), r->flags,
2285                 r->size.width, r->size.height,
2286                 r->area.left, r->area.right,
2287                 r->area.top, r->area.bottom);
2288 }
2289
2290 /****************************************************************************
2291 ****************************************************************************/
2292
2293 static void display_form_info2(struct spoolss_FormInfo2 *r)
2294 {
2295         printf("%s\n" \
2296                 "\tflag: %s (%d)\n" \
2297                 "\twidth: %d, length: %d\n" \
2298                 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2299                 r->form_name, get_form_flag(r->flags), r->flags,
2300                 r->size.width, r->size.height,
2301                 r->area.left, r->area.right,
2302                 r->area.top, r->area.bottom);
2303         printf("\tkeyword: %s\n", r->keyword);
2304         printf("\tstring_type: 0x%08x\n", r->string_type);
2305         printf("\tmui_dll: %s\n", r->mui_dll);
2306         printf("\tressource_id: 0x%08x\n", r->ressource_id);
2307         printf("\tdisplay_name: %s\n", r->display_name);
2308         printf("\tlang_id: %d\n", r->lang_id);
2309         printf("\n");
2310 }
2311
2312 /****************************************************************************
2313 ****************************************************************************/
2314
2315 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2316                                     int argc, const char **argv)
2317 {
2318         struct policy_handle handle;
2319         WERROR werror;
2320         NTSTATUS status;
2321         const char *printername;
2322         DATA_BLOB buffer;
2323         uint32_t offered = 0;
2324         union spoolss_FormInfo info;
2325         uint32_t needed;
2326         uint32_t level = 1;
2327         struct dcerpc_binding_handle *b = cli->binding_handle;
2328
2329         /* Parse the command arguments */
2330
2331         if (argc < 3 || argc > 5) {
2332                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2333                 return WERR_OK;
2334         }
2335
2336         /* Get a printer handle */
2337
2338         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2339
2340         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2341                                                printername,
2342                                                SEC_FLAG_MAXIMUM_ALLOWED,
2343                                                &handle);
2344         if (!W_ERROR_IS_OK(werror))
2345                 goto done;
2346
2347         if (argc == 4) {
2348                 level = atoi(argv[3]);
2349         }
2350
2351         /* Get the form */
2352
2353         status = dcerpc_spoolss_GetForm(b, mem_ctx,
2354                                         &handle,
2355                                         argv[2],
2356                                         level,
2357                                         NULL,
2358                                         offered,
2359                                         &info,
2360                                         &needed,
2361                                         &werror);
2362         if (!NT_STATUS_IS_OK(status)) {
2363                 werror = ntstatus_to_werror(status);
2364                 goto done;
2365         }
2366         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2367                 buffer = data_blob_talloc_zero(mem_ctx, needed);
2368                 offered = needed;
2369                 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2370                                                 &handle,
2371                                                 argv[2],
2372                                                 level,
2373                                                 &buffer,
2374                                                 offered,
2375                                                 &info,
2376                                                 &needed,
2377                                                 &werror);
2378                 if (!NT_STATUS_IS_OK(status)) {
2379                         werror = ntstatus_to_werror(status);
2380                         goto done;
2381                 }
2382         }
2383
2384         if (!W_ERROR_IS_OK(werror)) {
2385                 goto done;
2386         }
2387
2388         switch (level) {
2389         case 1:
2390                 display_form_info1(&info.info1);
2391                 break;
2392         case 2:
2393                 display_form_info2(&info.info2);
2394                 break;
2395         }
2396
2397  done:
2398         if (is_valid_policy_hnd(&handle)) {
2399                 WERROR _result;
2400                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2401         }
2402
2403         return werror;
2404 }
2405
2406 /****************************************************************************
2407 ****************************************************************************/
2408
2409 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2410                                        TALLOC_CTX *mem_ctx, int argc,
2411                                        const char **argv)
2412 {
2413         struct policy_handle handle;
2414         WERROR werror;
2415         NTSTATUS status;
2416         const char *printername;
2417         struct dcerpc_binding_handle *b = cli->binding_handle;
2418
2419         /* Parse the command arguments */
2420
2421         if (argc != 3) {
2422                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2423                 return WERR_OK;
2424         }
2425
2426         /* Get a printer handle */
2427
2428         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2429
2430         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2431                                                printername,
2432                                                SEC_FLAG_MAXIMUM_ALLOWED,
2433                                                &handle);
2434         if (!W_ERROR_IS_OK(werror))
2435                 goto done;
2436
2437         /* Delete the form */
2438
2439         status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2440                                            &handle,
2441                                            argv[2],
2442                                            &werror);
2443         if (!NT_STATUS_IS_OK(status)) {
2444                 werror = ntstatus_to_werror(status);
2445                 goto done;
2446         }
2447
2448  done:
2449         if (is_valid_policy_hnd(&handle)) {
2450                 WERROR _result;
2451                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2452         }
2453
2454         return werror;
2455 }
2456
2457 /****************************************************************************
2458 ****************************************************************************/
2459
2460 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2461                                        TALLOC_CTX *mem_ctx, int argc,
2462                                        const char **argv)
2463 {
2464         struct policy_handle handle;
2465         WERROR werror;
2466         const char *printername;
2467         uint32_t num_forms, level = 1, i;
2468         union spoolss_FormInfo *forms;
2469         struct dcerpc_binding_handle *b = cli->binding_handle;
2470
2471         /* Parse the command arguments */
2472
2473         if (argc < 2 || argc > 4) {
2474                 printf ("Usage: %s <printer> [level]\n", argv[0]);
2475                 return WERR_OK;
2476         }
2477
2478         /* Get a printer handle */
2479
2480         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2481
2482         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2483                                                printername,
2484                                                SEC_FLAG_MAXIMUM_ALLOWED,
2485                                                &handle);
2486         if (!W_ERROR_IS_OK(werror))
2487                 goto done;
2488
2489         if (argc == 3) {
2490                 level = atoi(argv[2]);
2491         }
2492
2493         /* Enumerate forms */
2494
2495         werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2496                                           &handle,
2497                                           level,
2498                                           0,
2499                                           &num_forms,
2500                                           &forms);
2501
2502         if (!W_ERROR_IS_OK(werror))
2503                 goto done;
2504
2505         /* Display output */
2506
2507         for (i = 0; i < num_forms; i++) {
2508                 switch (level) {
2509                 case 1:
2510                         display_form_info1(&forms[i].info1);
2511                         break;
2512                 case 2:
2513                         display_form_info2(&forms[i].info2);
2514                         break;
2515                 }
2516         }
2517
2518  done:
2519         if (is_valid_policy_hnd(&handle)) {
2520                 WERROR _result;
2521                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2522         }
2523
2524         return werror;
2525 }
2526
2527 /****************************************************************************
2528 ****************************************************************************/
2529
2530 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2531                                             TALLOC_CTX *mem_ctx,
2532                                             int argc, const char **argv)
2533 {
2534         WERROR result;
2535         NTSTATUS status;
2536         const char *printername;
2537         struct policy_handle pol;
2538         union spoolss_PrinterInfo info;
2539         enum winreg_Type type;
2540         union spoolss_PrinterData data;
2541         DATA_BLOB blob;
2542         struct dcerpc_binding_handle *b = cli->binding_handle;
2543
2544         /* parse the command arguments */
2545         if (argc < 5) {
2546                 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2547                         " <value> <data>\n",
2548                         argv[0]);
2549                 return WERR_OK;
2550         }
2551
2552         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2553
2554         type = REG_NONE;
2555
2556         if (strequal(argv[2], "string")) {
2557                 type = REG_SZ;
2558         }
2559
2560         if (strequal(argv[2], "binary")) {
2561                 type = REG_BINARY;
2562         }
2563
2564         if (strequal(argv[2], "dword")) {
2565                 type = REG_DWORD;
2566         }
2567
2568         if (strequal(argv[2], "multistring")) {
2569                 type = REG_MULTI_SZ;
2570         }
2571
2572         if (type == REG_NONE) {
2573                 printf("Unknown data type: %s\n", argv[2]);
2574                 result =  WERR_INVALID_PARAM;
2575                 goto done;
2576         }
2577
2578         /* get a printer handle */
2579
2580         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2581                                                printername,
2582                                                SEC_FLAG_MAXIMUM_ALLOWED,
2583                                                &pol);
2584         if (!W_ERROR_IS_OK(result)) {
2585                 goto done;
2586         }
2587
2588         result = rpccli_spoolss_getprinter(cli, mem_ctx,
2589                                            &pol,
2590                                            0,
2591                                            0,
2592                                            &info);
2593         if (!W_ERROR_IS_OK(result)) {
2594                 goto done;
2595         }
2596
2597         printf("%s\n", current_timestring(mem_ctx, true));
2598         printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2599
2600         /* Set the printer data */
2601
2602         switch (type) {
2603         case REG_SZ:
2604                 data.string = talloc_strdup(mem_ctx, argv[4]);
2605                 W_ERROR_HAVE_NO_MEMORY(data.string);
2606                 break;
2607         case REG_DWORD:
2608                 data.value = strtoul(argv[4], NULL, 10);
2609                 break;
2610         case REG_BINARY:
2611                 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2612                 break;
2613         case REG_MULTI_SZ: {
2614                 int i, num_strings;
2615                 const char **strings = NULL;
2616
2617                 for (i=4; i<argc; i++) {
2618                         if (strcmp(argv[i], "NULL") == 0) {
2619                                 argv[i] = "";
2620                         }
2621                         if (!add_string_to_array(mem_ctx, argv[i],
2622                                                  &strings,
2623                                                  &num_strings)) {
2624                                 result = WERR_NOMEM;
2625                                 goto done;
2626                         }
2627                 }
2628                 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2629                 if (!data.string_array) {
2630                         result = WERR_NOMEM;
2631                         goto done;
2632                 }
2633                 for (i=0; i < num_strings; i++) {
2634                         data.string_array[i] = strings[i];
2635                 }
2636                 break;
2637                 }
2638         default:
2639                 printf("Unknown data type: %s\n", argv[2]);
2640                 result = WERR_INVALID_PARAM;
2641                 goto done;
2642         }
2643
2644         result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2645         if (!W_ERROR_IS_OK(result)) {
2646                 goto done;
2647         }
2648
2649         status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2650                                                &pol,
2651                                                argv[3], /* value_name */
2652                                                type,
2653                                                blob.data,
2654                                                blob.length,
2655                                                &result);
2656         if (!NT_STATUS_IS_OK(status)) {
2657                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2658                 result = ntstatus_to_werror(status);
2659                 goto done;
2660         }
2661         if (!W_ERROR_IS_OK(result)) {
2662                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2663                 goto done;
2664         }
2665         printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2666
2667         result = rpccli_spoolss_getprinter(cli, mem_ctx,
2668                                            &pol,
2669                                            0,
2670                                            0,
2671                                            &info);
2672         if (!W_ERROR_IS_OK(result)) {
2673                 goto done;
2674         }
2675
2676         printf("%s\n", current_timestring(mem_ctx, true));
2677         printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2678
2679 done:
2680         /* cleanup */
2681         if (is_valid_policy_hnd(&pol)) {
2682                 WERROR _result;
2683                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2684         }
2685
2686         return result;
2687 }
2688
2689 /****************************************************************************
2690 ****************************************************************************/
2691
2692 static void display_job_info1(struct spoolss_JobInfo1 *r)
2693 {
2694         printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2695                r->user_name, r->document_name, r->text_status, r->pages_printed,
2696                r->total_pages);
2697 }
2698
2699 /****************************************************************************
2700 ****************************************************************************/
2701
2702 static void display_job_info2(struct spoolss_JobInfo2 *r)
2703 {
2704         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2705                r->position, r->job_id,
2706                r->user_name, r->document_name, r->text_status, r->pages_printed,
2707                r->total_pages, r->size);
2708 }
2709
2710 /****************************************************************************
2711 ****************************************************************************/
2712
2713 static void display_job_info3(struct spoolss_JobInfo3 *r)
2714 {
2715         printf("jobid[%d], next_jobid[%d]\n",
2716                 r->job_id, r->next_job_id);
2717 }
2718
2719 /****************************************************************************
2720 ****************************************************************************/
2721
2722 static void display_job_info4(struct spoolss_JobInfo4 *r)
2723 {
2724         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2725                r->position, r->job_id,
2726                r->user_name, r->document_name, r->text_status, r->pages_printed,
2727                r->total_pages, r->size, r->size_high);
2728 }
2729
2730 /****************************************************************************
2731 ****************************************************************************/
2732
2733 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2734                                       TALLOC_CTX *mem_ctx, int argc,
2735                                       const char **argv)
2736 {
2737         WERROR result;
2738         uint32_t level = 1, count, i;
2739         const char *printername;
2740         struct policy_handle hnd;
2741         union spoolss_JobInfo *info;
2742         struct dcerpc_binding_handle *b = cli->binding_handle;
2743
2744         if (argc < 2 || argc > 3) {
2745                 printf("Usage: %s printername [level]\n", argv[0]);
2746                 return WERR_OK;
2747         }
2748
2749         if (argc == 3) {
2750                 level = atoi(argv[2]);
2751         }
2752
2753         /* Open printer handle */
2754
2755         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2756
2757         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2758                                                printername,
2759                                                SEC_FLAG_MAXIMUM_ALLOWED,
2760                                                &hnd);
2761         if (!W_ERROR_IS_OK(result))
2762                 goto done;
2763
2764         /* Enumerate ports */
2765
2766         result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2767                                          &hnd,
2768                                          0, /* firstjob */
2769                                          1000, /* numjobs */
2770                                          level,
2771                                          0,
2772                                          &count,
2773                                          &info);
2774         if (!W_ERROR_IS_OK(result)) {
2775                 goto done;
2776         }
2777
2778         for (i = 0; i < count; i++) {
2779                 switch (level) {
2780                 case 1:
2781                         display_job_info1(&info[i].info1);
2782                         break;
2783                 case 2:
2784                         display_job_info2(&info[i].info2);
2785                         break;
2786                 default:
2787                         d_printf("unknown info level %d\n", level);
2788                         break;
2789                 }
2790         }
2791
2792 done:
2793         if (is_valid_policy_hnd(&hnd)) {
2794                 WERROR _result;
2795                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2796         }
2797
2798         return result;
2799 }
2800
2801 /****************************************************************************
2802 ****************************************************************************/
2803
2804 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2805                                   TALLOC_CTX *mem_ctx, int argc,
2806                                   const char **argv)
2807 {
2808         WERROR result;
2809         const char *printername;
2810         struct policy_handle hnd;
2811         uint32_t job_id;
2812         uint32_t level = 1;
2813         union spoolss_JobInfo info;
2814         struct dcerpc_binding_handle *b = cli->binding_handle;
2815
2816         if (argc < 3 || argc > 4) {
2817                 printf("Usage: %s printername job_id [level]\n", argv[0]);
2818                 return WERR_OK;
2819         }
2820
2821         job_id = atoi(argv[2]);
2822
2823         if (argc == 4) {
2824                 level = atoi(argv[3]);
2825         }
2826
2827         /* Open printer handle */
2828
2829         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2830
2831         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2832                                                printername,
2833                                                SEC_FLAG_MAXIMUM_ALLOWED,
2834                                                &hnd);
2835         if (!W_ERROR_IS_OK(result)) {
2836                 goto done;
2837         }
2838
2839         /* Enumerate ports */
2840
2841         result = rpccli_spoolss_getjob(cli, mem_ctx,
2842                                        &hnd,
2843                                        job_id,
2844                                        level,
2845                                        0,
2846                                        &info);
2847
2848         if (!W_ERROR_IS_OK(result)) {
2849                 goto done;
2850         }
2851
2852         switch (level) {
2853         case 1:
2854                 display_job_info1(&info.info1);
2855                 break;
2856         case 2:
2857                 display_job_info2(&info.info2);
2858                 break;
2859         case 3:
2860                 display_job_info3(&info.info3);
2861                 break;
2862         case 4:
2863                 display_job_info4(&info.info4);
2864                 break;
2865         default:
2866                 d_printf("unknown info level %d\n", level);
2867                 break;
2868         }
2869
2870 done:
2871         if (is_valid_policy_hnd(&hnd)) {
2872                 WERROR _result;
2873                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2874         }
2875
2876         return result;
2877 }
2878
2879 /****************************************************************************
2880 ****************************************************************************/
2881
2882 static struct {
2883         const char *name;
2884         enum spoolss_JobControl val;
2885 } cmdvals[] = {
2886         {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2887         {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2888         {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2889         {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2890         {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2891         {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2892         {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2893         {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2894         {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2895 };
2896
2897 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2898 {
2899         int i;
2900
2901         for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2902                 if (strequal(cmdvals[i].name, cmd)) {
2903                         return cmdvals[i].val;
2904                 }
2905         }
2906         return (enum spoolss_JobControl)atoi(cmd);
2907 }
2908
2909 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2910                                   TALLOC_CTX *mem_ctx, int argc,
2911                                   const char **argv)
2912 {
2913         WERROR result;
2914         NTSTATUS status;
2915         const char *printername;
2916         struct policy_handle hnd;
2917         uint32_t job_id;
2918         enum spoolss_JobControl command;
2919         struct dcerpc_binding_handle *b = cli->binding_handle;
2920
2921         if (argc != 4) {
2922                 printf("Usage: %s printername job_id command\n", argv[0]);
2923                 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2924                         "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2925                 return WERR_OK;
2926         }
2927
2928         job_id = atoi(argv[2]);
2929         command = parse_setjob_command(argv[3]);
2930
2931         /* Open printer handle */
2932
2933         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2934
2935         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2936                                                printername,
2937                                                SEC_FLAG_MAXIMUM_ALLOWED,
2938                                                &hnd);
2939         if (!W_ERROR_IS_OK(result)) {
2940                 goto done;
2941         }
2942
2943         /* Set Job */
2944
2945         status = dcerpc_spoolss_SetJob(b, mem_ctx,
2946                                        &hnd,
2947                                        job_id,
2948                                        NULL,
2949                                        command,
2950                                        &result);
2951         if (!NT_STATUS_IS_OK(status)) {
2952                 result = ntstatus_to_werror(status);
2953                 goto done;
2954         }
2955         if (!W_ERROR_IS_OK(result)) {
2956                 goto done;
2957         }
2958
2959 done:
2960         if (is_valid_policy_hnd(&hnd)) {
2961                 WERROR _result;
2962                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2963         }
2964
2965         return result;
2966 }
2967
2968 /****************************************************************************
2969 ****************************************************************************/
2970
2971 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2972                                     TALLOC_CTX *mem_ctx, int argc,
2973                                     const char **argv)
2974 {
2975         WERROR result;
2976         NTSTATUS status;
2977         const char *printername;
2978         struct policy_handle hnd;
2979         uint32_t value_needed;
2980         enum winreg_Type type;
2981         uint32_t data_needed;
2982         struct dcerpc_binding_handle *b = cli->binding_handle;
2983         struct spoolss_EnumPrinterData r;
2984
2985         if (argc != 2) {
2986                 printf("Usage: %s printername\n", argv[0]);
2987                 return WERR_OK;
2988         }
2989
2990         /* Open printer handle */
2991
2992         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2993
2994         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2995                                                printername,
2996                                                SEC_FLAG_MAXIMUM_ALLOWED,
2997                                                &hnd);
2998         if (!W_ERROR_IS_OK(result)) {
2999                 goto done;
3000         }
3001
3002         /* Enumerate data */
3003
3004         r.in.handle = &hnd;
3005         r.in.enum_index = 0;
3006         r.in.value_offered = 0;
3007         r.in.data_offered = 0;
3008         r.out.value_name = NULL;
3009         r.out.value_needed = &value_needed;
3010         r.out.type = &type;
3011         r.out.data = NULL;
3012         r.out.data_needed = &data_needed;
3013
3014         status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3015         if (!NT_STATUS_IS_OK(status)) {
3016                 result = ntstatus_to_werror(status);
3017                 goto done;
3018         }
3019
3020         if (!W_ERROR_IS_OK(r.out.result)) {
3021                 result = r.out.result;
3022                 goto done;
3023         }
3024
3025         r.in.data_offered       = *r.out.data_needed;
3026         r.in.value_offered      = *r.out.value_needed;
3027         r.out.data              = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3028         r.out.value_name        = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3029
3030         do {
3031
3032                 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3033                 if (!NT_STATUS_IS_OK(status)) {
3034                         result = ntstatus_to_werror(status);
3035                         goto done;
3036                 }
3037
3038                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3039                         result = WERR_OK;
3040                         break;
3041                 }
3042
3043                 r.in.enum_index++;
3044
3045                 {
3046                         struct regval_blob *v;
3047
3048                         v = regval_compose(talloc_tos(),
3049                                            r.out.value_name,
3050                                            *r.out.type,
3051                                            r.out.data,
3052                                            r.in.data_offered);
3053                         if (v == NULL) {
3054                                 result = WERR_NOMEM;
3055                                 goto done;
3056                         }
3057
3058                         display_reg_value(v);
3059                         talloc_free(v);
3060                 }
3061
3062         } while (W_ERROR_IS_OK(r.out.result));
3063
3064 done:
3065         if (is_valid_policy_hnd(&hnd)) {
3066                 WERROR _result;
3067                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3068         }
3069
3070         return result;
3071 }
3072
3073 /****************************************************************************
3074 ****************************************************************************/
3075
3076 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3077                                           TALLOC_CTX *mem_ctx, int argc,
3078                                           const char **argv)
3079 {
3080         WERROR result;
3081         uint32_t i;
3082         const char *printername;
3083         struct policy_handle hnd;
3084         uint32_t count;
3085         struct spoolss_PrinterEnumValues *info;
3086         struct dcerpc_binding_handle *b = cli->binding_handle;
3087
3088         if (argc != 3) {
3089                 printf("Usage: %s printername <keyname>\n", argv[0]);
3090                 return WERR_OK;
3091         }
3092
3093         /* Open printer handle */
3094
3095         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3096
3097         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3098                                                printername,
3099                                                SEC_FLAG_MAXIMUM_ALLOWED,
3100                                                &hnd);
3101         if (!W_ERROR_IS_OK(result)) {
3102                 goto done;
3103         }
3104
3105         /* Enumerate subkeys */
3106
3107         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3108                                                   &hnd,
3109                                                   argv[2],
3110                                                   0,
3111                                                   &count,
3112                                                   &info);
3113         if (!W_ERROR_IS_OK(result)) {
3114                 goto done;
3115         }
3116
3117         for (i=0; i < count; i++) {
3118                 display_printer_data(info[i].value_name,
3119                                      info[i].type,
3120                                      info[i].data->data,
3121                                      info[i].data->length);
3122         }
3123
3124  done:
3125         if (is_valid_policy_hnd(&hnd)) {
3126                 WERROR _result;
3127                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3128         }
3129
3130         return result;
3131 }
3132
3133 /****************************************************************************
3134 ****************************************************************************/
3135
3136 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3137                                           TALLOC_CTX *mem_ctx, int argc,
3138                                           const char **argv)
3139 {
3140         WERROR result;
3141         const char *printername;
3142         const char *keyname = NULL;
3143         struct policy_handle hnd;
3144         const char **key_buffer = NULL;
3145         int i;
3146         uint32_t offered = 0;
3147         struct dcerpc_binding_handle *b = cli->binding_handle;
3148
3149         if (argc < 2 || argc > 4) {
3150                 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3151                 return WERR_OK;
3152         }
3153
3154         if (argc >= 3) {
3155                 keyname = argv[2];
3156         } else {
3157                 keyname = "";
3158         }
3159
3160         if (argc == 4) {
3161                 offered = atoi(argv[3]);
3162         }
3163
3164         /* Open printer handle */
3165
3166         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3167
3168         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3169                                                printername,
3170                                                SEC_FLAG_MAXIMUM_ALLOWED,
3171                                                &hnd);
3172         if (!W_ERROR_IS_OK(result)) {
3173                 goto done;
3174         }
3175
3176         /* Enumerate subkeys */
3177
3178         result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3179                                                &hnd,
3180                                                keyname,
3181                                                &key_buffer,
3182                                                offered);
3183
3184         if (!W_ERROR_IS_OK(result)) {
3185                 goto done;
3186         }
3187
3188         for (i=0; key_buffer && key_buffer[i]; i++) {
3189                 printf("%s\n", key_buffer[i]);
3190         }
3191
3192  done:
3193
3194         if (is_valid_policy_hnd(&hnd)) {
3195                 WERROR _result;
3196                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3197         }
3198
3199         return result;
3200 }
3201
3202 /****************************************************************************
3203 ****************************************************************************/
3204
3205 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3206                                      TALLOC_CTX *mem_ctx, int argc,
3207                                      const char **argv)
3208 {
3209         const char *printername;
3210         const char *clientname;
3211         struct policy_handle hnd;
3212         WERROR result;
3213         NTSTATUS status;
3214         struct spoolss_NotifyOption option;
3215         struct dcerpc_binding_handle *b = cli->binding_handle;
3216
3217         if (argc != 2) {
3218                 printf("Usage: %s printername\n", argv[0]);
3219                 result = WERR_OK;
3220                 goto done;
3221         }
3222
3223         /* Open printer */
3224
3225         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3226
3227         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3228                                                printername,
3229                                                SEC_FLAG_MAXIMUM_ALLOWED,
3230                                                &hnd);
3231         if (!W_ERROR_IS_OK(result)) {
3232                 printf("Error opening %s\n", argv[1]);
3233                 goto done;
3234         }
3235
3236         /* Create spool options */
3237
3238         option.version = 2;
3239         option.count = 2;
3240
3241         option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3242         if (option.types == NULL) {
3243                 result = WERR_NOMEM;
3244                 goto done;
3245         }
3246
3247         option.types[0].type = PRINTER_NOTIFY_TYPE;
3248         option.types[0].count = 1;
3249         option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3250         if (option.types[0].fields == NULL) {
3251                 result = WERR_NOMEM;
3252                 goto done;
3253         }
3254         option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3255
3256         option.types[1].type = JOB_NOTIFY_TYPE;
3257         option.types[1].count = 1;
3258         option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3259         if (option.types[1].fields == NULL) {
3260                 result = WERR_NOMEM;
3261                 goto done;
3262         }
3263         option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3264
3265         clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3266         if (!clientname) {
3267                 result = WERR_NOMEM;
3268                 goto done;
3269         }
3270
3271         /* Send rffpcnex */
3272
3273         status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3274                                                                      &hnd,
3275                                                                      0,
3276                                                                      0,
3277                                                                      clientname,
3278                                                                      123,
3279                                                                      &option,
3280                                                                      &result);
3281         if (!NT_STATUS_IS_OK(status)) {
3282                 result = ntstatus_to_werror(status);
3283                 goto done;
3284         }
3285         if (!W_ERROR_IS_OK(result)) {
3286                 printf("Error rffpcnex %s\n", argv[1]);
3287                 goto done;
3288         }
3289
3290 done:
3291         if (is_valid_policy_hnd(&hnd)) {
3292                 WERROR _result;
3293                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3294         }
3295
3296         return result;
3297 }
3298
3299 /****************************************************************************
3300 ****************************************************************************/
3301
3302 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3303                              struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3304 {
3305         union spoolss_PrinterInfo info1, info2;
3306         WERROR werror;
3307         TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3308
3309         printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3310         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3311                                            hnd1,
3312                                            2,
3313                                            0,
3314                                            &info1);
3315         if ( !W_ERROR_IS_OK(werror) ) {
3316                 printf("failed (%s)\n", win_errstr(werror));
3317                 talloc_destroy(mem_ctx);
3318                 return false;
3319         }
3320         printf("ok\n");
3321
3322         printf("Retrieving printer properties for %s...", cli2->desthost);
3323         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3324                                            hnd2,
3325                                            2,
3326                                            0,
3327                                            &info2);
3328         if ( !W_ERROR_IS_OK(werror) ) {
3329                 printf("failed (%s)\n", win_errstr(werror));
3330                 talloc_destroy(mem_ctx);
3331                 return false;
3332         }
3333         printf("ok\n");
3334
3335         talloc_destroy(mem_ctx);
3336
3337         return true;
3338 }
3339
3340 /****************************************************************************
3341 ****************************************************************************/
3342
3343 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3344                                      struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3345 {
3346         union spoolss_PrinterInfo info1, info2;
3347         WERROR werror;
3348         TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3349         struct security_descriptor *sd1, *sd2;
3350         bool result = true;
3351
3352
3353         printf("Retrieving printer security for %s...", cli1->desthost);
3354         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3355                                            hnd1,
3356                                            3,
3357                                            0,
3358                                            &info1);
3359         if ( !W_ERROR_IS_OK(werror) ) {
3360                 printf("failed (%s)\n", win_errstr(werror));
3361                 result = false;
3362                 goto done;
3363         }
3364         printf("ok\n");
3365
3366         printf("Retrieving printer security for %s...", cli2->desthost);
3367         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3368                                            hnd2,
3369                                            3,
3370                                            0,
3371                                            &info2);
3372         if ( !W_ERROR_IS_OK(werror) ) {
3373                 printf("failed (%s)\n", win_errstr(werror));
3374                 result = false;
3375                 goto done;
3376         }
3377         printf("ok\n");
3378
3379
3380         printf("++ ");
3381
3382         sd1 = info1.info3.secdesc;
3383         sd2 = info2.info3.secdesc;
3384
3385         if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3386                 printf("NULL secdesc!\n");
3387                 result = false;
3388                 goto done;
3389         }
3390
3391         if (!security_descriptor_equal( sd1, sd2 ) ) {
3392                 printf("Security Descriptors *not* equal!\n");
3393                 result = false;
3394                 goto done;
3395         }
3396
3397         printf("Security descriptors match\n");
3398
3399 done:
3400         talloc_destroy(mem_ctx);
3401         return result;
3402 }
3403
3404
3405 /****************************************************************************
3406 ****************************************************************************/
3407
3408 extern struct user_auth_info *rpcclient_auth_info;
3409
3410 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3411                                      TALLOC_CTX *mem_ctx, int argc,
3412                                      const char **argv)
3413 {
3414         const char *printername;
3415         char *printername_path = NULL;
3416         struct cli_state *cli_server2 = NULL;
3417         struct rpc_pipe_client *cli2 = NULL;
3418         struct policy_handle hPrinter1, hPrinter2;
3419         NTSTATUS nt_status;
3420         WERROR werror;
3421
3422         if ( argc != 3 )  {
3423                 printf("Usage: %s <printer> <server>\n", argv[0]);
3424                 return WERR_OK;
3425         }
3426
3427         printername = argv[1];
3428
3429         /* first get the connection to the remote server */
3430
3431         nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3432                                         NULL, 0,
3433                                         "IPC$", "IPC",
3434                                         get_cmdline_auth_info_username(rpcclient_auth_info),
3435                                         lp_workgroup(),
3436                                         get_cmdline_auth_info_password(rpcclient_auth_info),
3437                                         get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3438                                         get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3439
3440         if ( !NT_STATUS_IS_OK(nt_status) )
3441                 return WERR_GENERAL_FAILURE;
3442
3443         nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3444                                              &cli2);
3445         if (!NT_STATUS_IS_OK(nt_status)) {
3446                 printf("failed to open spoolss pipe on server %s (%s)\n",
3447                         argv[2], nt_errstr(nt_status));
3448                 return WERR_GENERAL_FAILURE;
3449         }
3450
3451         /* now open up both printers */
3452
3453         RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3454
3455         printf("Opening %s...", printername_path);
3456
3457         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3458                                                printername_path,
3459                                                PRINTER_ALL_ACCESS,
3460                                                &hPrinter1);
3461         if ( !W_ERROR_IS_OK(werror) ) {
3462                 printf("failed (%s)\n", win_errstr(werror));
3463                 goto done;
3464         }
3465         printf("ok\n");
3466
3467         RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3468
3469         printf("Opening %s...", printername_path);
3470         werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3471                                                printername_path,
3472                                                PRINTER_ALL_ACCESS,
3473                                                &hPrinter2);
3474         if ( !W_ERROR_IS_OK(werror) ) {
3475                  printf("failed (%s)\n", win_errstr(werror));
3476                 goto done;
3477         }
3478         printf("ok\n");
3479
3480         compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3481         compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3482 #if 0
3483         compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3484 #endif
3485
3486
3487 done:
3488         /* cleanup */
3489
3490         printf("Closing printers...");
3491         {
3492                 WERROR _result;
3493                 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3494                 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3495         }
3496         printf("ok\n");
3497
3498         /* close the second remote connection */
3499
3500         cli_shutdown( cli_server2 );
3501         return WERR_OK;
3502 }
3503
3504 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3505 {
3506         printf("print_processor_name: %s\n", r->print_processor_name);
3507 }
3508
3509 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3510                                      TALLOC_CTX *mem_ctx, int argc,
3511                                      const char **argv)
3512 {
3513         WERROR werror;
3514         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3515         uint32_t num_procs, level = 1, i;
3516         union spoolss_PrintProcessorInfo *procs;
3517
3518         /* Parse the command arguments */
3519
3520         if (argc < 1 || argc > 4) {
3521                 printf ("Usage: %s [environment] [level]\n", argv[0]);
3522                 return WERR_OK;
3523         }
3524
3525         if (argc >= 2) {
3526                 environment = argv[1];
3527         }
3528
3529         if (argc == 3) {
3530                 level = atoi(argv[2]);
3531         }
3532
3533         /* Enumerate Print Processors */
3534
3535         werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3536                                                     cli->srv_name_slash,
3537                                                     environment,
3538                                                     level,
3539                                                     0,
3540                                                     &num_procs,
3541                                                     &procs);
3542         if (!W_ERROR_IS_OK(werror))
3543