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