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