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