s3-libsmb: move protos to libsmb/proto.h
[metze/samba/wip.git] / source3 / rpcclient / cmd_spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Gerald Carter                2001-2005
6    Copyright (C) Tim Potter                        2000
7    Copyright (C) Andrew Tridgell              1992-1999
8    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9    Copyright (C) Guenther Deschner                 2009
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
30 #include "registry/reg_objects.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(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(struct regval_blob *value)
768 {
769         const char *text = NULL;
770         DATA_BLOB blob;
771
772         switch(regval_type(value)) {
773         case REG_DWORD:
774                 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
775                        *((uint32_t *) regval_data_p(value)));
776                 break;
777         case REG_SZ:
778                 blob = data_blob_const(regval_data_p(value), regval_size(value));
779                 pull_reg_sz(talloc_tos(), &blob, &text);
780                 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
781                 break;
782         case REG_BINARY: {
783                 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
784                 size_t i, len;
785                 printf("%s: REG_BINARY:", regval_name(value));
786                 len = strlen(hex);
787                 for (i=0; i<len; i++) {
788                         if (hex[i] == '\0') {
789                                 break;
790                         }
791                         if (i%40 == 0) {
792                                 putchar('\n');
793                         }
794                         putchar(hex[i]);
795                 }
796                 TALLOC_FREE(hex);
797                 putchar('\n');
798                 break;
799         }
800         case REG_MULTI_SZ: {
801                 uint32_t i;
802                 const char **values;
803                 blob = data_blob_const(regval_data_p(value), regval_size(value));
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", regval_name(value));
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", regval_name(value), regval_type(value));
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
836         result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
837         if (!W_ERROR_IS_OK(result)) {
838                 return;
839         }
840
841         switch (type) {
842         case REG_DWORD:
843                 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
844                 break;
845         case REG_SZ:
846                 printf("%s: REG_SZ: %s\n", v, r.string);
847                 break;
848         case REG_BINARY: {
849                 char *hex = hex_encode_talloc(NULL,
850                         r.binary.data, r.binary.length);
851                 size_t len;
852                 printf("%s: REG_BINARY:", v);
853                 len = strlen(hex);
854                 for (i=0; i<len; i++) {
855                         if (hex[i] == '\0') {
856                                 break;
857                         }
858                         if (i%40 == 0) {
859                                 putchar('\n');
860                         }
861                         putchar(hex[i]);
862                 }
863                 TALLOC_FREE(hex);
864                 putchar('\n');
865                 break;
866         }
867         case REG_MULTI_SZ:
868                 printf("%s: REG_MULTI_SZ: ", v);
869                 for (i=0; r.string_array[i] != NULL; i++) {
870                         printf("%s ", r.string_array[i]);
871                 }
872                 printf("\n");
873                 break;
874         default:
875                 printf("%s: unknown type 0x%02x:\n", v, type);
876                 break;
877         }
878 }
879
880 /****************************************************************************
881 ****************************************************************************/
882
883 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
884                                            TALLOC_CTX *mem_ctx,
885                                            int argc, const char **argv)
886 {
887         struct policy_handle pol;
888         WERROR          result;
889         fstring         printername;
890         const char *valuename;
891         enum winreg_Type type;
892         uint8_t *data;
893         uint32_t needed;
894         struct dcerpc_binding_handle *b = cli->binding_handle;
895
896         if (argc != 3) {
897                 printf("Usage: %s <printername> <valuename>\n", argv[0]);
898                 printf("<printername> of . queries print server\n");
899                 return WERR_OK;
900         }
901         valuename = argv[2];
902
903         /* Open a printer handle */
904
905         if (strncmp(argv[1], ".", sizeof(".")) == 0)
906                 fstrcpy(printername, cli->srv_name_slash);
907         else
908                 slprintf(printername, sizeof(printername)-1, "%s\\%s",
909                           cli->srv_name_slash, argv[1]);
910
911         /* get a printer handle */
912
913         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
914                                                printername,
915                                                SEC_FLAG_MAXIMUM_ALLOWED,
916                                                &pol);
917         if (!W_ERROR_IS_OK(result))
918                 goto done;
919
920         /* Get printer info */
921
922         result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
923                                                &pol,
924                                                valuename,
925                                                0,
926                                                &type,
927                                                &needed,
928                                                &data);
929         if (!W_ERROR_IS_OK(result))
930                 goto done;
931
932         /* Display printer data */
933
934         display_printer_data(valuename, type, data, needed);
935
936  done:
937         if (is_valid_policy_hnd(&pol)) {
938                 WERROR _result;
939                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
940         }
941
942         return result;
943 }
944
945 /****************************************************************************
946 ****************************************************************************/
947
948 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
949                                              TALLOC_CTX *mem_ctx,
950                                              int argc, const char **argv)
951 {
952         struct policy_handle pol;
953         WERROR          result;
954         NTSTATUS        status;
955         fstring         printername;
956         const char *valuename, *keyname;
957
958         enum winreg_Type type;
959         uint8_t *data = NULL;
960         uint32_t offered = 0;
961         uint32_t needed;
962         struct dcerpc_binding_handle *b = cli->binding_handle;
963
964         if (argc != 4) {
965                 printf("Usage: %s <printername> <keyname> <valuename>\n",
966                        argv[0]);
967                 printf("<printername> of . queries print server\n");
968                 return WERR_OK;
969         }
970         valuename = argv[3];
971         keyname = argv[2];
972
973         /* Open a printer handle */
974
975         if (strncmp(argv[1], ".", sizeof(".")) == 0)
976                 fstrcpy(printername, cli->srv_name_slash);
977         else
978                 slprintf(printername, sizeof(printername)-1, "%s\\%s",
979                           cli->srv_name_slash, argv[1]);
980
981         /* get a printer handle */
982
983         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
984                                                printername,
985                                                SEC_FLAG_MAXIMUM_ALLOWED,
986                                                &pol);
987         if (!W_ERROR_IS_OK(result))
988                 goto done;
989
990         /* Get printer info */
991
992         data = talloc_zero_array(mem_ctx, uint8_t, offered);
993         if (!data) {
994                 goto done;
995         }
996
997         status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
998                                                  &pol,
999                                                  keyname,
1000                                                  valuename,
1001                                                  &type,
1002                                                  data,
1003                                                  offered,
1004                                                  &needed,
1005                                                  &result);
1006         if (!NT_STATUS_IS_OK(status)) {
1007                 result = ntstatus_to_werror(status);
1008                 goto done;
1009         }
1010         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1011                 offered = needed;
1012                 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1013                 if (!data) {
1014                         goto done;
1015                 }
1016                 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1017                                                          &pol,
1018                                                          keyname,
1019                                                          valuename,
1020                                                          &type,
1021                                                          data,
1022                                                          offered,
1023                                                          &needed,
1024                                                          &result);
1025         }
1026
1027         if (!NT_STATUS_IS_OK(status)) {
1028                 result = ntstatus_to_werror(status);
1029                 goto done;
1030         }
1031
1032         if (!W_ERROR_IS_OK(result))
1033                 goto done;
1034
1035         /* Display printer data */
1036
1037         display_printer_data(valuename, type, data, needed);
1038
1039
1040  done:
1041         if (is_valid_policy_hnd(&pol)) {
1042                 WERROR _result;
1043                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1044         }
1045
1046         return result;
1047 }
1048
1049 /****************************************************************************
1050 ****************************************************************************/
1051
1052 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1053 {
1054         if (!r) {
1055                 return;
1056         }
1057
1058         printf("Printer Driver Info 1:\n");
1059         printf("\tDriver Name: [%s]\n", r->driver_name);
1060         printf("\n");
1061 }
1062
1063 /****************************************************************************
1064 ****************************************************************************/
1065
1066 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1067 {
1068         if (!r) {
1069                 return;
1070         }
1071
1072         printf("Printer Driver Info 2:\n");
1073         printf("\tVersion: [%x]\n", r->version);
1074         printf("\tDriver Name: [%s]\n", r->driver_name);
1075         printf("\tArchitecture: [%s]\n", r->architecture);
1076         printf("\tDriver Path: [%s]\n", r->driver_path);
1077         printf("\tDatafile: [%s]\n", r->data_file);
1078         printf("\tConfigfile: [%s]\n", r->config_file);
1079         printf("\n");
1080 }
1081
1082 /****************************************************************************
1083 ****************************************************************************/
1084
1085 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1086 {
1087         int i;
1088
1089         if (!r) {
1090                 return;
1091         }
1092
1093         printf("Printer Driver Info 3:\n");
1094         printf("\tVersion: [%x]\n", r->version);
1095         printf("\tDriver Name: [%s]\n", r->driver_name);
1096         printf("\tArchitecture: [%s]\n", r->architecture);
1097         printf("\tDriver Path: [%s]\n", r->driver_path);
1098         printf("\tDatafile: [%s]\n", r->data_file);
1099         printf("\tConfigfile: [%s]\n", r->config_file);
1100         printf("\tHelpfile: [%s]\n", r->help_file);
1101
1102         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1103                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1104         }
1105
1106         printf("\tMonitorname: [%s]\n", r->monitor_name);
1107         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1108         printf("\n");
1109 }
1110
1111 /****************************************************************************
1112 ****************************************************************************/
1113
1114 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1115 {
1116         int i;
1117
1118         if (!r) {
1119                 return;
1120         }
1121
1122         printf("Printer Driver Info 4:\n");
1123         printf("\tVersion: [%x]\n", r->version);
1124         printf("\tDriver Name: [%s]\n", r->driver_name);
1125         printf("\tArchitecture: [%s]\n", r->architecture);
1126         printf("\tDriver Path: [%s]\n", r->driver_path);
1127         printf("\tDatafile: [%s]\n", r->data_file);
1128         printf("\tConfigfile: [%s]\n", r->config_file);
1129         printf("\tHelpfile: [%s]\n", r->help_file);
1130
1131         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1132                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1133         }
1134
1135         printf("\tMonitorname: [%s]\n", r->monitor_name);
1136         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1137
1138         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1139                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1140         }
1141         printf("\n");
1142 }
1143
1144 /****************************************************************************
1145 ****************************************************************************/
1146
1147 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1148 {
1149         if (!r) {
1150                 return;
1151         }
1152
1153         printf("Printer Driver Info 5:\n");
1154         printf("\tVersion: [%x]\n", r->version);
1155         printf("\tDriver Name: [%s]\n", r->driver_name);
1156         printf("\tArchitecture: [%s]\n", r->architecture);
1157         printf("\tDriver Path: [%s]\n", r->driver_path);
1158         printf("\tDatafile: [%s]\n", r->data_file);
1159         printf("\tConfigfile: [%s]\n", r->config_file);
1160         printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1161         printf("\tConfig Version: [0x%x]\n", r->config_version);
1162         printf("\tDriver Version: [0x%x]\n", r->driver_version);
1163         printf("\n");
1164 }
1165
1166 /****************************************************************************
1167 ****************************************************************************/
1168
1169 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1170 {
1171         int i;
1172
1173         if (!r) {
1174                 return;
1175         }
1176
1177         printf("Printer Driver Info 6:\n");
1178         printf("\tVersion: [%x]\n", r->version);
1179         printf("\tDriver Name: [%s]\n", r->driver_name);
1180         printf("\tArchitecture: [%s]\n", r->architecture);
1181         printf("\tDriver Path: [%s]\n", r->driver_path);
1182         printf("\tDatafile: [%s]\n", r->data_file);
1183         printf("\tConfigfile: [%s]\n", r->config_file);
1184         printf("\tHelpfile: [%s]\n", r->help_file);
1185
1186         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1187                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1188         }
1189
1190         printf("\tMonitorname: [%s]\n", r->monitor_name);
1191         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1192
1193         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1194                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1195         }
1196
1197         printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1198         printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1199         printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1200         printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1201         printf("\tHardware ID: [%s]\n", r->hardware_id);
1202         printf("\tProvider: [%s]\n", r->provider);
1203
1204         printf("\n");
1205 }
1206
1207 /****************************************************************************
1208 ****************************************************************************/
1209
1210 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1211 {
1212         int i;
1213
1214         if (!r) {
1215                 return;
1216         }
1217
1218         printf("Printer Driver Info 8:\n");
1219         printf("\tVersion: [%x]\n", r->version);
1220         printf("\tDriver Name: [%s]\n", r->driver_name);
1221         printf("\tArchitecture: [%s]\n", r->architecture);
1222         printf("\tDriver Path: [%s]\n", r->driver_path);
1223         printf("\tDatafile: [%s]\n", r->data_file);
1224         printf("\tConfigfile: [%s]\n", r->config_file);
1225         printf("\tHelpfile: [%s]\n", r->help_file);
1226         printf("\tMonitorname: [%s]\n", r->monitor_name);
1227         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1228
1229         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1230                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1231         }
1232
1233         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1234                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1235         }
1236
1237         printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1238         printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1239         printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1240         printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1241         printf("\tHardware ID: [%s]\n", r->hardware_id);
1242         printf("\tProvider: [%s]\n", r->provider);
1243         printf("\tPrint Processor: [%s]\n", r->print_processor);
1244         printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1245         for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1246                 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1247         }
1248         printf("\tInf Path: [%s]\n", r->inf_path);
1249         printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1250         for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1251                 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1252         }
1253         printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1254         printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1255                 (long long unsigned int)r->min_inbox_driver_ver_version);
1256
1257         printf("\n");
1258 }
1259
1260 /****************************************************************************
1261 ****************************************************************************/
1262
1263 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1264                                     TALLOC_CTX *mem_ctx,
1265                                     int argc, const char **argv)
1266 {
1267         struct policy_handle pol;
1268         WERROR          werror;
1269         uint32_t        level = 3;
1270         const char      *printername;
1271         uint32_t        i;
1272         bool            success = false;
1273         union spoolss_DriverInfo info;
1274         uint32_t server_major_version;
1275         uint32_t server_minor_version;
1276         struct dcerpc_binding_handle *b = cli->binding_handle;
1277
1278         if ((argc == 1) || (argc > 3)) {
1279                 printf("Usage: %s <printername> [level]\n", argv[0]);
1280                 return WERR_OK;
1281         }
1282
1283         /* get the arguments need to open the printer handle */
1284
1285         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1286
1287         if (argc == 3) {
1288                 level = atoi(argv[2]);
1289         }
1290
1291         /* Open a printer handle */
1292
1293         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1294                                                printername,
1295                                                PRINTER_ACCESS_USE,
1296                                                &pol);
1297         if (!W_ERROR_IS_OK(werror)) {
1298                 printf("Error opening printer handle for %s!\n", printername);
1299                 return werror;
1300         }
1301
1302         /* loop through and print driver info level for each architecture */
1303
1304         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1305
1306                 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1307                                                           &pol,
1308                                                           archi_table[i].long_archi,
1309                                                           level,
1310                                                           0, /* offered */
1311                                                           archi_table[i].version,
1312                                                           2,
1313                                                           &info,
1314                                                           &server_major_version,
1315                                                           &server_minor_version);
1316                 if (!W_ERROR_IS_OK(werror)) {
1317                         continue;
1318                 }
1319
1320                 /* need at least one success */
1321
1322                 success = true;
1323
1324                 printf("\n[%s]\n", archi_table[i].long_archi);
1325
1326                 switch (level) {
1327                 case 1:
1328                         display_print_driver1(&info.info1);
1329                         break;
1330                 case 2:
1331                         display_print_driver2(&info.info2);
1332                         break;
1333                 case 3:
1334                         display_print_driver3(&info.info3);
1335                         break;
1336                 case 4:
1337                         display_print_driver4(&info.info4);
1338                         break;
1339                 case 5:
1340                         display_print_driver5(&info.info5);
1341                         break;
1342                 case 6:
1343                         display_print_driver6(&info.info6);
1344                         break;
1345                 case 8:
1346                         display_print_driver8(&info.info8);
1347                         break;
1348                 default:
1349                         printf("unknown info level %d\n", level);
1350                         break;
1351                 }
1352         }
1353
1354         /* Cleanup */
1355
1356         if (is_valid_policy_hnd(&pol)) {
1357                 WERROR _result;
1358                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1359         }
1360
1361         if (success) {
1362                 werror = WERR_OK;
1363         }
1364
1365         return werror;
1366 }
1367
1368 /****************************************************************************
1369 ****************************************************************************/
1370
1371 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1372                                           TALLOC_CTX *mem_ctx,
1373                                           const char *architecture,
1374                                           uint32_t level)
1375 {
1376         WERROR werror;
1377         uint32_t count = 0;
1378         union spoolss_DriverInfo *info = NULL;
1379         uint32_t j;
1380
1381         werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1382                                                    cli->srv_name_slash,
1383                                                    architecture,
1384                                                    level,
1385                                                    0,
1386                                                    &count,
1387                                                    &info);
1388
1389         if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1390                 printf("Server does not support environment [%s]\n",
1391                         architecture);
1392                 return WERR_OK;
1393         }
1394
1395         if (count == 0) {
1396                 return WERR_OK;
1397         }
1398
1399         if (!W_ERROR_IS_OK(werror)) {
1400                 printf("Error getting driver for environment [%s] - %s\n",
1401                         architecture, win_errstr(werror));
1402                 return werror;
1403         }
1404
1405         printf("\n[%s]\n", architecture);
1406
1407         switch (level) {
1408         case 1:
1409                 for (j=0; j < count; j++) {
1410                         display_print_driver1(&info[j].info1);
1411                 }
1412                 break;
1413         case 2:
1414                 for (j=0; j < count; j++) {
1415                         display_print_driver2(&info[j].info2);
1416                 }
1417                 break;
1418         case 3:
1419                 for (j=0; j < count; j++) {
1420                         display_print_driver3(&info[j].info3);
1421                 }
1422                 break;
1423         case 4:
1424                 for (j=0; j < count; j++) {
1425                         display_print_driver4(&info[j].info4);
1426                 }
1427                 break;
1428         case 5:
1429                 for (j=0; j < count; j++) {
1430                         display_print_driver5(&info[j].info5);
1431                 }
1432                 break;
1433         case 6:
1434                 for (j=0; j < count; j++) {
1435                         display_print_driver6(&info[j].info6);
1436                 }
1437                 break;
1438         case 8:
1439                 for (j=0; j < count; j++) {
1440                         display_print_driver8(&info[j].info8);
1441                 }
1442                 break;
1443         default:
1444                 printf("unknown info level %d\n", level);
1445                 return WERR_UNKNOWN_LEVEL;
1446         }
1447
1448         return werror;
1449 }
1450
1451 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1452                                          TALLOC_CTX *mem_ctx,
1453                                          int argc, const char **argv)
1454 {
1455         WERROR werror = WERR_OK;
1456         uint32_t        level = 1;
1457         uint32_t        i;
1458         const char *architecture = NULL;
1459
1460         if (argc > 3) {
1461                 printf("Usage: enumdrivers [level] [architecture]\n");
1462                 return WERR_OK;
1463         }
1464
1465         if (argc >= 2) {
1466                 level = atoi(argv[1]);
1467         }
1468
1469         if (argc == 3) {
1470                 architecture = argv[2];
1471         }
1472
1473         if (architecture) {
1474                 return enum_driver_by_architecture(cli, mem_ctx,
1475                                                    architecture,
1476                                                    level);
1477         }
1478
1479         /* loop through and print driver info level for each architecture */
1480         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1481                 /* check to see if we already asked for this architecture string */
1482
1483                 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1484                         continue;
1485                 }
1486
1487                 werror = enum_driver_by_architecture(cli, mem_ctx,
1488                                                      archi_table[i].long_archi,
1489                                                      level);
1490                 if (!W_ERROR_IS_OK(werror)) {
1491                         break;
1492                 }
1493         }
1494
1495         return werror;
1496 }
1497
1498 /****************************************************************************
1499 ****************************************************************************/
1500
1501 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1502 {
1503         printf("\tDirectory Name:[%s]\n", r->directory_name);
1504 }
1505
1506 /****************************************************************************
1507 ****************************************************************************/
1508
1509 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1510                                          TALLOC_CTX *mem_ctx,
1511                                          int argc, const char **argv)
1512 {
1513         WERROR result;
1514         NTSTATUS status;
1515         const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1516         DATA_BLOB buffer;
1517         uint32_t offered;
1518         union spoolss_DriverDirectoryInfo info;
1519         uint32_t needed;
1520         struct dcerpc_binding_handle *b = cli->binding_handle;
1521
1522         if (argc > 2) {
1523                 printf("Usage: %s [environment]\n", argv[0]);
1524                 return WERR_OK;
1525         }
1526
1527         /* Get the arguments need to open the printer handle */
1528
1529         if (argc == 2) {
1530                 env = argv[1];
1531         }
1532
1533         /* Get the directory.  Only use Info level 1 */
1534
1535         status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1536                                                           cli->srv_name_slash,
1537                                                           env,
1538                                                           1,
1539                                                           NULL, /* buffer */
1540                                                           0, /* offered */
1541                                                           NULL, /* info */
1542                                                           &needed,
1543                                                           &result);
1544         if (!NT_STATUS_IS_OK(status)) {
1545                 return ntstatus_to_werror(status);
1546         }
1547         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1548                 offered = needed;
1549                 buffer = data_blob_talloc_zero(mem_ctx, needed);
1550
1551                 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1552                                                                   cli->srv_name_slash,
1553                                                                   env,
1554                                                                   1,
1555                                                                   &buffer,
1556                                                                   offered,
1557                                                                   &info,
1558                                                                   &needed,
1559                                                                   &result);
1560                 if (!NT_STATUS_IS_OK(status)) {
1561                         return ntstatus_to_werror(status);
1562                 }
1563         }
1564
1565         if (W_ERROR_IS_OK(result)) {
1566                 display_printdriverdir_1(&info.info1);
1567         }
1568
1569         return result;
1570 }
1571
1572 /****************************************************************************
1573 ****************************************************************************/
1574
1575 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1576                                struct spoolss_AddDriverInfo3 *info,
1577                                const char *arch)
1578 {
1579
1580         int i;
1581
1582         for (i=0; archi_table[i].long_archi != NULL; i++)
1583         {
1584                 if (strcmp(arch, archi_table[i].short_archi) == 0)
1585                 {
1586                         info->version = archi_table[i].version;
1587                         info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1588                         break;
1589                 }
1590         }
1591
1592         if (archi_table[i].long_archi == NULL)
1593         {
1594                 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1595         }
1596
1597         return;
1598 }
1599
1600
1601 /**************************************************************************
1602  wrapper for strtok to get the next parameter from a delimited list.
1603  Needed to handle the empty parameter string denoted by "NULL"
1604  *************************************************************************/
1605
1606 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1607                                 const char *delim, const char **dest,
1608                                 char **saveptr)
1609 {
1610         char    *ptr;
1611
1612         /* get the next token */
1613         ptr = strtok_r(str, delim, saveptr);
1614
1615         /* a string of 'NULL' is used to represent an empty
1616            parameter because two consecutive delimiters
1617            will not return an empty string.  See man strtok(3)
1618            for details */
1619         if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1620                 ptr = NULL;
1621         }
1622
1623         if (dest != NULL) {
1624                 *dest = talloc_strdup(mem_ctx, ptr);
1625         }
1626
1627         return ptr;
1628 }
1629
1630 /********************************************************************************
1631  fill in the members of a spoolss_AddDriverInfo3 struct using a character
1632  string in the form of
1633          <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1634              <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1635              <Default Data Type>:<Comma Separated list of Files>
1636  *******************************************************************************/
1637
1638 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1639                                     char *args)
1640 {
1641         char    *str, *str2;
1642         int count = 0;
1643         char *saveptr = NULL;
1644         struct spoolss_StringArray *deps;
1645         const char **file_array = NULL;
1646         int i;
1647
1648         /* fill in the UNISTR fields */
1649         str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1650         str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1651         str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1652         str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1653         str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1654         str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1655         str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1656
1657         /* <Comma Separated List of Dependent Files> */
1658         /* save the beginning of the string */
1659         str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1660         str = str2;
1661
1662         /* begin to strip out each filename */
1663         str = strtok_r(str, ",", &saveptr);
1664
1665         /* no dependent files, we are done */
1666         if (!str) {
1667                 return true;
1668         }
1669
1670         deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1671         if (!deps) {
1672                 return false;
1673         }
1674
1675         while (str != NULL) {
1676                 add_string_to_array(deps, str, &file_array, &count);
1677                 str = strtok_r(NULL, ",", &saveptr);
1678         }
1679
1680         deps->string = talloc_zero_array(deps, const char *, count + 1);
1681         if (!deps->string) {
1682                 return false;
1683         }
1684
1685         for (i=0; i < count; i++) {
1686                 deps->string[i] = file_array[i];
1687         }
1688
1689         r->dependent_files = deps;
1690
1691         return true;
1692 }
1693
1694 /****************************************************************************
1695 ****************************************************************************/
1696
1697 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1698                                              TALLOC_CTX *mem_ctx,
1699                                              int argc, const char **argv)
1700 {
1701         WERROR result;
1702         NTSTATUS status;
1703         uint32_t                  level = 3;
1704         struct spoolss_AddDriverInfoCtr info_ctr;
1705         struct spoolss_AddDriverInfo3 info3;
1706         const char              *arch;
1707         char                    *driver_args;
1708         struct dcerpc_binding_handle *b = cli->binding_handle;
1709
1710         /* parse the command arguments */
1711         if (argc != 3 && argc != 4)
1712         {
1713                 printf ("Usage: %s <Environment> \\\n", argv[0]);
1714                 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1715                 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1716                 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1717                 printf ("\t[version]\n");
1718
1719             return WERR_OK;
1720         }
1721
1722         /* Fill in the spoolss_AddDriverInfo3 struct */
1723         ZERO_STRUCT(info3);
1724
1725         arch = cmd_spoolss_get_short_archi(argv[1]);
1726         if (!arch) {
1727                 printf ("Error Unknown architecture [%s]\n", argv[1]);
1728                 return WERR_INVALID_PARAM;
1729         }
1730
1731         set_drv_info_3_env(mem_ctx, &info3, arch);
1732
1733         driver_args = talloc_strdup( mem_ctx, argv[2] );
1734         if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1735         {
1736                 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1737                 return WERR_INVALID_PARAM;
1738         }
1739
1740         /* if printer driver version specified, override the default version
1741          * used by the architecture.  This allows installation of Windows
1742          * 2000 (version 3) printer drivers. */
1743         if (argc == 4)
1744         {
1745                 info3.version = atoi(argv[3]);
1746         }
1747
1748
1749         info_ctr.level          = level;
1750         info_ctr.info.info3     = &info3;
1751
1752         status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1753                                                  cli->srv_name_slash,
1754                                                  &info_ctr,
1755                                                  &result);
1756         if (!NT_STATUS_IS_OK(status)) {
1757                 return ntstatus_to_werror(status);
1758         }
1759         if (W_ERROR_IS_OK(result)) {
1760                 printf ("Printer Driver %s successfully installed.\n",
1761                         info3.driver_name);
1762         }
1763
1764         return result;
1765 }
1766
1767
1768 /****************************************************************************
1769 ****************************************************************************/
1770
1771 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1772                                          TALLOC_CTX *mem_ctx,
1773                                          int argc, const char **argv)
1774 {
1775         WERROR result;
1776         struct spoolss_SetPrinterInfoCtr info_ctr;
1777         struct spoolss_SetPrinterInfo2 info2;
1778
1779         /* parse the command arguments */
1780         if (argc != 5)
1781         {
1782                 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1783                 return WERR_OK;
1784         }
1785
1786         /* Fill in the DRIVER_INFO_2 struct */
1787         ZERO_STRUCT(info2);
1788
1789         info2.printername       = argv[1];
1790         info2.drivername        = argv[3];
1791         info2.sharename         = argv[2];
1792         info2.portname          = argv[4];
1793         info2.comment           = "Created by rpcclient";
1794         info2.printprocessor    = "winprint";
1795         info2.datatype          = "RAW";
1796         info2.devmode_ptr       = 0;
1797         info2.secdesc_ptr       = 0;
1798         info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
1799         info2.priority          = 0;
1800         info2.defaultpriority   = 0;
1801         info2.starttime         = 0;
1802         info2.untiltime         = 0;
1803
1804         /* These three fields must not be used by AddPrinter()
1805            as defined in the MS Platform SDK documentation..
1806            --jerry
1807         info2.status            = 0;
1808         info2.cjobs             = 0;
1809         info2.averageppm        = 0;
1810         */
1811
1812         info_ctr.level = 2;
1813         info_ctr.info.info2 = &info2;
1814
1815         result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1816                                              &info_ctr);
1817         if (W_ERROR_IS_OK(result))
1818                 printf ("Printer %s successfully installed.\n", argv[1]);
1819
1820         return result;
1821 }
1822
1823 /****************************************************************************
1824 ****************************************************************************/
1825
1826 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1827                                       TALLOC_CTX *mem_ctx,
1828                                       int argc, const char **argv)
1829 {
1830         struct policy_handle    pol;
1831         WERROR                  result;
1832         NTSTATUS                status;
1833         uint32_t                level = 2;
1834         const char              *printername;
1835         union spoolss_PrinterInfo info;
1836         struct spoolss_SetPrinterInfoCtr info_ctr;
1837         struct spoolss_SetPrinterInfo2 info2;
1838         struct spoolss_DevmodeContainer devmode_ctr;
1839         struct sec_desc_buf secdesc_ctr;
1840         struct dcerpc_binding_handle *b = cli->binding_handle;
1841
1842         ZERO_STRUCT(devmode_ctr);
1843         ZERO_STRUCT(secdesc_ctr);
1844
1845         /* parse the command arguments */
1846         if (argc != 3)
1847         {
1848                 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1849                 return WERR_OK;
1850         }
1851
1852         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1853
1854         /* Get a printer handle */
1855
1856         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1857                                                printername,
1858                                                PRINTER_ALL_ACCESS,
1859                                                &pol);
1860         if (!W_ERROR_IS_OK(result))
1861                 goto done;
1862
1863         /* Get printer info */
1864
1865         result = rpccli_spoolss_getprinter(cli, mem_ctx,
1866                                            &pol,
1867                                            level,
1868                                            0,
1869                                            &info);
1870         if (!W_ERROR_IS_OK(result)) {
1871                 printf ("Unable to retrieve printer information!\n");
1872                 goto done;
1873         }
1874
1875         /* Set the printer driver */
1876
1877         spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1878         info2.drivername = argv[2];
1879
1880         info_ctr.level = 2;
1881         info_ctr.info.info2 = &info2;
1882
1883         status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1884                                            &pol,
1885                                            &info_ctr,
1886                                            &devmode_ctr,
1887                                            &secdesc_ctr,
1888                                            0, /* command */
1889                                            &result);
1890         if (!NT_STATUS_IS_OK(status)) {
1891                 result = ntstatus_to_werror(status);
1892                 goto done;
1893         }
1894         if (!W_ERROR_IS_OK(result)) {
1895                 printf("SetPrinter call failed!\n");
1896                 goto done;
1897         }
1898
1899         printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1900
1901 done:
1902         /* Cleanup */
1903
1904         if (is_valid_policy_hnd(&pol)) {
1905                 WERROR _result;
1906                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1907         }
1908
1909         return result;
1910 }
1911
1912
1913 /****************************************************************************
1914 ****************************************************************************/
1915
1916 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1917                                          TALLOC_CTX *mem_ctx,
1918                                          int argc, const char **argv)
1919 {
1920         WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1921         NTSTATUS status;
1922         struct dcerpc_binding_handle *b = cli->binding_handle;
1923
1924         int   i;
1925         int vers = -1;
1926
1927         const char *arch = NULL;
1928         uint32_t delete_flags = 0;
1929
1930         /* parse the command arguments */
1931         if (argc < 2 || argc > 4) {
1932                 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1933                 return WERR_OK;
1934         }
1935
1936         if (argc >= 3)
1937                 arch = argv[2];
1938         if (argc == 4)
1939                 vers = atoi (argv[3]);
1940
1941         if (vers >= 0) {
1942                 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1943         }
1944
1945         /* delete the driver for all architectures */
1946         for (i=0; archi_table[i].long_archi; i++) {
1947
1948                 if (arch &&  !strequal( archi_table[i].long_archi, arch))
1949                         continue;
1950
1951                 if (vers >= 0 && archi_table[i].version != vers)
1952                         continue;
1953
1954                 /* make the call to remove the driver */
1955                 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1956                                                               cli->srv_name_slash,
1957                                                               archi_table[i].long_archi,
1958                                                               argv[1],
1959                                                               delete_flags,
1960                                                               archi_table[i].version,
1961                                                               &result);
1962                 if (!NT_STATUS_IS_OK(status)) {
1963                         return ntstatus_to_werror(status);
1964                 }
1965                 if ( !W_ERROR_IS_OK(result) )
1966                 {
1967                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1968                                 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1969                                         argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1970                         }
1971                 }
1972                 else
1973                 {
1974                         printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1975                         archi_table[i].long_archi, archi_table[i].version);
1976                         ret = WERR_OK;
1977                 }
1978         }
1979
1980         return ret;
1981 }
1982
1983
1984 /****************************************************************************
1985 ****************************************************************************/
1986
1987 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1988                                          TALLOC_CTX *mem_ctx,
1989                                          int argc, const char **argv)
1990 {
1991         WERROR result = WERR_OK;
1992         NTSTATUS status;
1993         int                     i;
1994         struct dcerpc_binding_handle *b = cli->binding_handle;
1995
1996         /* parse the command arguments */
1997         if (argc != 2) {
1998                 printf ("Usage: %s <driver>\n", argv[0]);
1999                 return WERR_OK;
2000         }
2001
2002         /* delete the driver for all architectures */
2003         for (i=0; archi_table[i].long_archi; i++) {
2004                 result = WERR_OK;
2005
2006                 /* make the call to remove the driver */
2007                 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2008                                                             cli->srv_name_slash,
2009                                                             archi_table[i].long_archi,
2010                                                             argv[1],
2011                                                             &result);
2012                 if (!NT_STATUS_IS_OK(status)) {
2013                         result = ntstatus_to_werror(status);
2014                         continue;
2015                 }
2016                 if ( !W_ERROR_IS_OK(result) ) {
2017                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2018                                 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2019                                         argv[1], archi_table[i].long_archi,
2020                                         win_errstr(result));
2021                         }
2022                 } else {
2023                         printf ("Driver %s removed for arch [%s].\n", argv[1],
2024                                 archi_table[i].long_archi);
2025                 }
2026         }
2027
2028         return result;
2029 }
2030
2031 /****************************************************************************
2032 ****************************************************************************/
2033
2034 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2035                                             TALLOC_CTX *mem_ctx,
2036                                             int argc, const char **argv)
2037 {
2038         WERROR result;
2039         NTSTATUS status;
2040         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2041         DATA_BLOB buffer;
2042         uint32_t offered;
2043         union spoolss_PrintProcessorDirectoryInfo info;
2044         uint32_t needed;
2045         struct dcerpc_binding_handle *b = cli->binding_handle;
2046
2047         /* parse the command arguments */
2048         if (argc > 2) {
2049                 printf ("Usage: %s [environment]\n", argv[0]);
2050                 return WERR_OK;
2051         }
2052
2053         if (argc == 2) {
2054                 environment = argv[1];
2055         }
2056
2057         status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2058                                                            cli->srv_name_slash,
2059                                                            environment,
2060                                                            1,
2061                                                            NULL, /* buffer */
2062                                                            0, /* offered */
2063                                                            NULL, /* info */
2064                                                            &needed,
2065                                                            &result);
2066         if (!NT_STATUS_IS_OK(status)) {
2067                 return ntstatus_to_werror(status);
2068         }
2069         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2070                 offered = needed;
2071                 buffer = data_blob_talloc_zero(mem_ctx, needed);
2072
2073                 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2074                                                                    cli->srv_name_slash,
2075                                                                    environment,
2076                                                                    1,
2077                                                                    &buffer,
2078                                                                    offered,
2079                                                                    &info,
2080                                                                    &needed,
2081                                                                    &result);
2082                 if (!NT_STATUS_IS_OK(status)) {
2083                         return ntstatus_to_werror(status);
2084                 }
2085         }
2086
2087         if (W_ERROR_IS_OK(result)) {
2088                 printf("%s\n", info.info1.directory_name);
2089         }
2090
2091         return result;
2092 }
2093
2094 /****************************************************************************
2095 ****************************************************************************/
2096
2097 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2098                                     int argc, const char **argv)
2099 {
2100         struct policy_handle handle;
2101         WERROR werror;
2102         NTSTATUS status;
2103         const char *printername;
2104         union spoolss_AddFormInfo info;
2105         struct spoolss_AddFormInfo1 info1;
2106         struct spoolss_AddFormInfo2 info2;
2107         uint32_t level = 1;
2108         struct dcerpc_binding_handle *b = cli->binding_handle;
2109
2110         /* Parse the command arguments */
2111
2112         if (argc < 3 || argc > 5) {
2113                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2114                 return WERR_OK;
2115         }
2116
2117         /* Get a printer handle */
2118
2119         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2120
2121         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2122                                                printername,
2123                                                PRINTER_ALL_ACCESS,
2124                                                &handle);
2125         if (!W_ERROR_IS_OK(werror))
2126                 goto done;
2127
2128         /* Dummy up some values for the form data */
2129
2130         if (argc == 4) {
2131                 level = atoi(argv[3]);
2132         }
2133
2134         switch (level) {
2135         case 1:
2136                 info1.flags             = SPOOLSS_FORM_USER;
2137                 info1.form_name         = argv[2];
2138                 info1.size.width        = 100;
2139                 info1.size.height       = 100;
2140                 info1.area.left         = 0;
2141                 info1.area.top          = 10;
2142                 info1.area.right        = 20;
2143                 info1.area.bottom       = 30;
2144
2145                 info.info1 = &info1;
2146
2147                 break;
2148         case 2:
2149                 info2.flags             = SPOOLSS_FORM_USER;
2150                 info2.form_name         = argv[2];
2151                 info2.size.width        = 100;
2152                 info2.size.height       = 100;
2153                 info2.area.left         = 0;
2154                 info2.area.top          = 10;
2155                 info2.area.right        = 20;
2156                 info2.area.bottom       = 30;
2157                 info2.keyword           = argv[2];
2158                 info2.string_type       = SPOOLSS_FORM_STRING_TYPE_NONE;
2159                 info2.mui_dll           = NULL;
2160                 info2.ressource_id      = 0;
2161                 info2.display_name      = argv[2];
2162                 info2.lang_id           = 0;
2163
2164                 info.info2 = &info2;
2165
2166                 break;
2167         default:
2168                 werror = WERR_INVALID_PARAM;
2169                 goto done;
2170         }
2171
2172         /* Add the form */
2173
2174
2175         status = dcerpc_spoolss_AddForm(b, mem_ctx,
2176                                         &handle,
2177                                         level,
2178                                         info,
2179                                         &werror);
2180         if (!NT_STATUS_IS_OK(status)) {
2181                 werror = ntstatus_to_werror(status);
2182                 goto done;
2183         }
2184  done:
2185         if (is_valid_policy_hnd(&handle)) {
2186                 WERROR _result;
2187                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2188         }
2189
2190         return werror;
2191 }
2192
2193 /****************************************************************************
2194 ****************************************************************************/
2195
2196 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2197                                     int argc, const char **argv)
2198 {
2199         struct policy_handle handle;
2200         WERROR werror;
2201         NTSTATUS status;
2202         const char *printername;
2203         union spoolss_AddFormInfo info;
2204         struct spoolss_AddFormInfo1 info1;
2205         struct dcerpc_binding_handle *b = cli->binding_handle;
2206
2207         /* Parse the command arguments */
2208
2209         if (argc != 3) {
2210                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2211                 return WERR_OK;
2212         }
2213
2214         /* Get a printer handle */
2215
2216         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2217
2218         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2219                                                printername,
2220                                                SEC_FLAG_MAXIMUM_ALLOWED,
2221                                                &handle);
2222         if (!W_ERROR_IS_OK(werror))
2223                 goto done;
2224
2225         /* Dummy up some values for the form data */
2226
2227         info1.flags             = SPOOLSS_FORM_PRINTER;
2228         info1.size.width        = 100;
2229         info1.size.height       = 100;
2230         info1.area.left         = 0;
2231         info1.area.top          = 1000;
2232         info1.area.right        = 2000;
2233         info1.area.bottom       = 3000;
2234         info1.form_name         = argv[2];
2235
2236         info.info1 = &info1;
2237
2238         /* Set the form */
2239
2240         status = dcerpc_spoolss_SetForm(b, mem_ctx,
2241                                         &handle,
2242                                         argv[2],
2243                                         1,
2244                                         info,
2245                                         &werror);
2246         if (!NT_STATUS_IS_OK(status)) {
2247                 werror = ntstatus_to_werror(status);
2248                 goto done;
2249         }
2250  done:
2251         if (is_valid_policy_hnd(&handle)) {
2252                 WERROR _result;
2253                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2254         }
2255
2256         return werror;
2257 }
2258
2259 /****************************************************************************
2260 ****************************************************************************/
2261
2262 static const char *get_form_flag(int form_flag)
2263 {
2264         switch (form_flag) {
2265         case SPOOLSS_FORM_USER:
2266                 return "FORM_USER";
2267         case SPOOLSS_FORM_BUILTIN:
2268                 return "FORM_BUILTIN";
2269         case SPOOLSS_FORM_PRINTER:
2270                 return "FORM_PRINTER";
2271         default:
2272                 return "unknown";
2273         }
2274 }
2275
2276 /****************************************************************************
2277 ****************************************************************************/
2278
2279 static void display_form_info1(struct spoolss_FormInfo1 *r)
2280 {
2281         printf("%s\n" \
2282                 "\tflag: %s (%d)\n" \
2283                 "\twidth: %d, length: %d\n" \
2284                 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2285                 r->form_name, get_form_flag(r->flags), r->flags,
2286                 r->size.width, r->size.height,
2287                 r->area.left, r->area.right,
2288                 r->area.top, r->area.bottom);
2289 }
2290
2291 /****************************************************************************
2292 ****************************************************************************/
2293
2294 static void display_form_info2(struct spoolss_FormInfo2 *r)
2295 {
2296         printf("%s\n" \
2297                 "\tflag: %s (%d)\n" \
2298                 "\twidth: %d, length: %d\n" \
2299                 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2300                 r->form_name, get_form_flag(r->flags), r->flags,
2301                 r->size.width, r->size.height,
2302                 r->area.left, r->area.right,
2303                 r->area.top, r->area.bottom);
2304         printf("\tkeyword: %s\n", r->keyword);
2305         printf("\tstring_type: 0x%08x\n", r->string_type);
2306         printf("\tmui_dll: %s\n", r->mui_dll);
2307         printf("\tressource_id: 0x%08x\n", r->ressource_id);
2308         printf("\tdisplay_name: %s\n", r->display_name);
2309         printf("\tlang_id: %d\n", r->lang_id);
2310         printf("\n");
2311 }
2312
2313 /****************************************************************************
2314 ****************************************************************************/
2315
2316 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2317                                     int argc, const char **argv)
2318 {
2319         struct policy_handle handle;
2320         WERROR werror;
2321         NTSTATUS status;
2322         const char *printername;
2323         DATA_BLOB buffer;
2324         uint32_t offered = 0;
2325         union spoolss_FormInfo info;
2326         uint32_t needed;
2327         uint32_t level = 1;
2328         struct dcerpc_binding_handle *b = cli->binding_handle;
2329
2330         /* Parse the command arguments */
2331
2332         if (argc < 3 || argc > 5) {
2333                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2334                 return WERR_OK;
2335         }
2336
2337         /* Get a printer handle */
2338
2339         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2340
2341         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2342                                                printername,
2343                                                SEC_FLAG_MAXIMUM_ALLOWED,
2344                                                &handle);
2345         if (!W_ERROR_IS_OK(werror))
2346                 goto done;
2347
2348         if (argc == 4) {
2349                 level = atoi(argv[3]);
2350         }
2351
2352         /* Get the form */
2353
2354         status = dcerpc_spoolss_GetForm(b, mem_ctx,
2355                                         &handle,
2356                                         argv[2],
2357                                         level,
2358                                         NULL,
2359                                         offered,
2360                                         &info,
2361                                         &needed,
2362                                         &werror);
2363         if (!NT_STATUS_IS_OK(status)) {
2364                 werror = ntstatus_to_werror(status);
2365                 goto done;
2366         }
2367         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2368                 buffer = data_blob_talloc_zero(mem_ctx, needed);
2369                 offered = needed;
2370                 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2371                                                 &handle,
2372                                                 argv[2],
2373                                                 level,
2374                                                 &buffer,
2375                                                 offered,
2376                                                 &info,
2377                                                 &needed,
2378                                                 &werror);
2379                 if (!NT_STATUS_IS_OK(status)) {
2380                         werror = ntstatus_to_werror(status);
2381                         goto done;
2382                 }
2383         }
2384
2385         if (!W_ERROR_IS_OK(werror)) {
2386                 goto done;
2387         }
2388
2389         switch (level) {
2390         case 1:
2391                 display_form_info1(&info.info1);
2392                 break;
2393         case 2:
2394                 display_form_info2(&info.info2);
2395                 break;
2396         }
2397
2398  done:
2399         if (is_valid_policy_hnd(&handle)) {
2400                 WERROR _result;
2401                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2402         }
2403
2404         return werror;
2405 }
2406
2407 /****************************************************************************
2408 ****************************************************************************/
2409
2410 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2411                                        TALLOC_CTX *mem_ctx, int argc,
2412                                        const char **argv)
2413 {
2414         struct policy_handle handle;
2415         WERROR werror;
2416         NTSTATUS status;
2417         const char *printername;
2418         struct dcerpc_binding_handle *b = cli->binding_handle;
2419
2420         /* Parse the command arguments */
2421
2422         if (argc != 3) {
2423                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2424                 return WERR_OK;
2425         }
2426
2427         /* Get a printer handle */
2428
2429         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2430
2431         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2432                                                printername,
2433                                                SEC_FLAG_MAXIMUM_ALLOWED,
2434                                                &handle);
2435         if (!W_ERROR_IS_OK(werror))
2436                 goto done;
2437
2438         /* Delete the form */
2439
2440         status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2441                                            &handle,
2442                                            argv[2],
2443                                            &werror);
2444         if (!NT_STATUS_IS_OK(status)) {
2445                 werror = ntstatus_to_werror(status);
2446                 goto done;
2447         }
2448
2449  done:
2450         if (is_valid_policy_hnd(&handle)) {
2451                 WERROR _result;
2452                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2453         }
2454
2455         return werror;
2456 }
2457
2458 /****************************************************************************
2459 ****************************************************************************/
2460
2461 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2462                                        TALLOC_CTX *mem_ctx, int argc,
2463                                        const char **argv)
2464 {
2465         struct policy_handle handle;
2466         WERROR werror;
2467         const char *printername;
2468         uint32_t num_forms, level = 1, i;
2469         union spoolss_FormInfo *forms;
2470         struct dcerpc_binding_handle *b = cli->binding_handle;
2471
2472         /* Parse the command arguments */
2473
2474         if (argc < 2 || argc > 4) {
2475                 printf ("Usage: %s <printer> [level]\n", argv[0]);
2476                 return WERR_OK;
2477         }
2478
2479         /* Get a printer handle */
2480
2481         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2482
2483         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2484                                                printername,
2485                                                SEC_FLAG_MAXIMUM_ALLOWED,
2486                                                &handle);
2487         if (!W_ERROR_IS_OK(werror))
2488                 goto done;
2489
2490         if (argc == 3) {
2491                 level = atoi(argv[2]);
2492         }
2493
2494         /* Enumerate forms */
2495
2496         werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2497                                           &handle,
2498                                           level,
2499                                           0,
2500                                           &num_forms,
2501                                           &forms);
2502
2503         if (!W_ERROR_IS_OK(werror))
2504                 goto done;
2505
2506         /* Display output */
2507
2508         for (i = 0; i < num_forms; i++) {
2509                 switch (level) {
2510                 case 1:
2511                         display_form_info1(&forms[i].info1);
2512                         break;
2513                 case 2:
2514                         display_form_info2(&forms[i].info2);
2515                         break;
2516                 }
2517         }
2518
2519  done:
2520         if (is_valid_policy_hnd(&handle)) {
2521                 WERROR _result;
2522                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2523         }
2524
2525         return werror;
2526 }
2527
2528 /****************************************************************************
2529 ****************************************************************************/
2530
2531 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2532                                             TALLOC_CTX *mem_ctx,
2533                                             int argc, const char **argv)
2534 {
2535         WERROR result;
2536         NTSTATUS status;
2537         const char *printername;
2538         struct policy_handle pol;
2539         union spoolss_PrinterInfo info;
2540         enum winreg_Type type;
2541         union spoolss_PrinterData data;
2542         DATA_BLOB blob;
2543         struct dcerpc_binding_handle *b = cli->binding_handle;
2544
2545         /* parse the command arguments */
2546         if (argc < 5) {
2547                 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2548                         " <value> <data>\n",
2549                         argv[0]);
2550                 return WERR_OK;
2551         }
2552
2553         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2554
2555         type = REG_NONE;
2556
2557         if (strequal(argv[2], "string")) {
2558                 type = REG_SZ;
2559         }
2560
2561         if (strequal(argv[2], "binary")) {
2562                 type = REG_BINARY;
2563         }
2564
2565         if (strequal(argv[2], "dword")) {
2566                 type = REG_DWORD;
2567         }
2568
2569         if (strequal(argv[2], "multistring")) {
2570                 type = REG_MULTI_SZ;
2571         }
2572
2573         if (type == REG_NONE) {
2574                 printf("Unknown data type: %s\n", argv[2]);
2575                 result =  WERR_INVALID_PARAM;
2576                 goto done;
2577         }
2578
2579         /* get a printer handle */
2580
2581         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2582                                                printername,
2583                                                SEC_FLAG_MAXIMUM_ALLOWED,
2584                                                &pol);
2585         if (!W_ERROR_IS_OK(result)) {
2586                 goto done;
2587         }
2588
2589         result = rpccli_spoolss_getprinter(cli, mem_ctx,
2590                                            &pol,
2591                                            0,
2592                                            0,
2593                                            &info);
2594         if (!W_ERROR_IS_OK(result)) {
2595                 goto done;
2596         }
2597
2598         printf("%s\n", current_timestring(mem_ctx, true));
2599         printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2600
2601         /* Set the printer data */
2602
2603         switch (type) {
2604         case REG_SZ:
2605                 data.string = talloc_strdup(mem_ctx, argv[4]);
2606                 W_ERROR_HAVE_NO_MEMORY(data.string);
2607                 break;
2608         case REG_DWORD:
2609                 data.value = strtoul(argv[4], NULL, 10);
2610                 break;
2611         case REG_BINARY:
2612                 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2613                 break;
2614         case REG_MULTI_SZ: {
2615                 int i, num_strings;
2616                 const char **strings = NULL;
2617
2618                 for (i=4; i<argc; i++) {
2619                         if (strcmp(argv[i], "NULL") == 0) {
2620                                 argv[i] = "";
2621                         }
2622                         if (!add_string_to_array(mem_ctx, argv[i],
2623                                                  &strings,
2624                                                  &num_strings)) {
2625                                 result = WERR_NOMEM;
2626                                 goto done;
2627                         }
2628                 }
2629                 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2630                 if (!data.string_array) {
2631                         result = WERR_NOMEM;
2632                         goto done;
2633                 }
2634                 for (i=0; i < num_strings; i++) {
2635                         data.string_array[i] = strings[i];
2636                 }
2637                 break;
2638                 }
2639         default:
2640                 printf("Unknown data type: %s\n", argv[2]);
2641                 result = WERR_INVALID_PARAM;
2642                 goto done;
2643         }
2644
2645         result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2646         if (!W_ERROR_IS_OK(result)) {
2647                 goto done;
2648         }
2649
2650         status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2651                                                &pol,
2652                                                argv[3], /* value_name */
2653                                                type,
2654                                                blob.data,
2655                                                blob.length,
2656                                                &result);
2657         if (!NT_STATUS_IS_OK(status)) {
2658                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2659                 result = ntstatus_to_werror(status);
2660                 goto done;
2661         }
2662         if (!W_ERROR_IS_OK(result)) {
2663                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2664                 goto done;
2665         }
2666         printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2667
2668         result = rpccli_spoolss_getprinter(cli, mem_ctx,
2669                                            &pol,
2670                                            0,
2671                                            0,
2672                                            &info);
2673         if (!W_ERROR_IS_OK(result)) {
2674                 goto done;
2675         }
2676
2677         printf("%s\n", current_timestring(mem_ctx, true));
2678         printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2679
2680 done:
2681         /* cleanup */
2682         if (is_valid_policy_hnd(&pol)) {
2683                 WERROR _result;
2684                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2685         }
2686
2687         return result;
2688 }
2689
2690 /****************************************************************************
2691 ****************************************************************************/
2692
2693 static void display_job_info1(struct spoolss_JobInfo1 *r)
2694 {
2695         printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2696                r->user_name, r->document_name, r->text_status, r->pages_printed,
2697                r->total_pages);
2698 }
2699
2700 /****************************************************************************
2701 ****************************************************************************/
2702
2703 static void display_job_info2(struct spoolss_JobInfo2 *r)
2704 {
2705         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2706                r->position, r->job_id,
2707                r->user_name, r->document_name, r->text_status, r->pages_printed,
2708                r->total_pages, r->size);
2709 }
2710
2711 /****************************************************************************
2712 ****************************************************************************/
2713
2714 static void display_job_info3(struct spoolss_JobInfo3 *r)
2715 {
2716         printf("jobid[%d], next_jobid[%d]\n",
2717                 r->job_id, r->next_job_id);
2718 }
2719
2720 /****************************************************************************
2721 ****************************************************************************/
2722
2723 static void display_job_info4(struct spoolss_JobInfo4 *r)
2724 {
2725         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2726                r->position, r->job_id,
2727                r->user_name, r->document_name, r->text_status, r->pages_printed,
2728                r->total_pages, r->size, r->size_high);
2729 }
2730
2731 /****************************************************************************
2732 ****************************************************************************/
2733
2734 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2735                                       TALLOC_CTX *mem_ctx, int argc,
2736                                       const char **argv)
2737 {
2738         WERROR result;
2739         uint32_t level = 1, count, i;
2740         const char *printername;
2741         struct policy_handle hnd;
2742         union spoolss_JobInfo *info;
2743         struct dcerpc_binding_handle *b = cli->binding_handle;
2744
2745         if (argc < 2 || argc > 3) {
2746                 printf("Usage: %s printername [level]\n", argv[0]);
2747                 return WERR_OK;
2748         }
2749
2750         if (argc == 3) {
2751                 level = atoi(argv[2]);
2752         }
2753
2754         /* Open printer handle */
2755
2756         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2757
2758         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2759                                                printername,
2760                                                SEC_FLAG_MAXIMUM_ALLOWED,
2761                                                &hnd);
2762         if (!W_ERROR_IS_OK(result))
2763                 goto done;
2764
2765         /* Enumerate ports */
2766
2767         result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2768                                          &hnd,
2769                                          0, /* firstjob */
2770                                          1000, /* numjobs */
2771                                          level,
2772                                          0,
2773                                          &count,
2774                                          &info);
2775         if (!W_ERROR_IS_OK(result)) {
2776                 goto done;
2777         }
2778
2779         for (i = 0; i < count; i++) {
2780                 switch (level) {
2781                 case 1:
2782                         display_job_info1(&info[i].info1);
2783                         break;
2784                 case 2:
2785                         display_job_info2(&info[i].info2);
2786                         break;
2787                 default:
2788                         d_printf("unknown info level %d\n", level);
2789                         break;
2790                 }
2791         }
2792
2793 done:
2794         if (is_valid_policy_hnd(&hnd)) {
2795                 WERROR _result;
2796                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2797         }
2798
2799         return result;
2800 }
2801
2802 /****************************************************************************
2803 ****************************************************************************/
2804
2805 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2806                                   TALLOC_CTX *mem_ctx, int argc,
2807                                   const char **argv)
2808 {
2809         WERROR result;
2810         const char *printername;
2811         struct policy_handle hnd;
2812         uint32_t job_id;
2813         uint32_t level = 1;
2814         union spoolss_JobInfo info;
2815         struct dcerpc_binding_handle *b = cli->binding_handle;
2816
2817         if (argc < 3 || argc > 4) {
2818                 printf("Usage: %s printername job_id [level]\n", argv[0]);
2819                 return WERR_OK;
2820         }
2821
2822         job_id = atoi(argv[2]);
2823
2824         if (argc == 4) {
2825                 level = atoi(argv[3]);
2826         }
2827
2828         /* Open printer handle */
2829
2830         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2831
2832         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2833                                                printername,
2834                                                SEC_FLAG_MAXIMUM_ALLOWED,
2835                                                &hnd);
2836         if (!W_ERROR_IS_OK(result)) {
2837                 goto done;
2838         }
2839
2840         /* Enumerate ports */
2841
2842         result = rpccli_spoolss_getjob(cli, mem_ctx,
2843                                        &hnd,
2844                                        job_id,
2845                                        level,
2846                                        0,
2847                                        &info);
2848
2849         if (!W_ERROR_IS_OK(result)) {
2850                 goto done;
2851         }
2852
2853         switch (level) {
2854         case 1:
2855                 display_job_info1(&info.info1);
2856                 break;
2857         case 2:
2858                 display_job_info2(&info.info2);
2859                 break;
2860         case 3:
2861                 display_job_info3(&info.info3);
2862                 break;
2863         case 4:
2864                 display_job_info4(&info.info4);
2865                 break;
2866         default:
2867                 d_printf("unknown info level %d\n", level);
2868                 break;
2869         }
2870
2871 done:
2872         if (is_valid_policy_hnd(&hnd)) {
2873                 WERROR _result;
2874                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2875         }
2876
2877         return result;
2878 }
2879
2880 /****************************************************************************
2881 ****************************************************************************/
2882
2883 static struct {
2884         const char *name;
2885         enum spoolss_JobControl val;
2886 } cmdvals[] = {
2887         {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2888         {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2889         {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2890         {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2891         {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2892         {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2893         {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2894         {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2895         {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2896 };
2897
2898 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2899 {
2900         int i;
2901
2902         for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2903                 if (strequal(cmdvals[i].name, cmd)) {
2904                         return cmdvals[i].val;
2905                 }
2906         }
2907         return (enum spoolss_JobControl)atoi(cmd);
2908 }
2909
2910 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2911                                   TALLOC_CTX *mem_ctx, int argc,
2912                                   const char **argv)
2913 {
2914         WERROR result;
2915         NTSTATUS status;
2916         const char *printername;
2917         struct policy_handle hnd;
2918         uint32_t job_id;
2919         enum spoolss_JobControl command;
2920         struct dcerpc_binding_handle *b = cli->binding_handle;
2921
2922         if (argc != 4) {
2923                 printf("Usage: %s printername job_id command\n", argv[0]);
2924                 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2925                         "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2926                 return WERR_OK;
2927         }
2928
2929         job_id = atoi(argv[2]);
2930         command = parse_setjob_command(argv[3]);
2931
2932         /* Open printer handle */
2933
2934         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2935
2936         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2937                                                printername,
2938                                                SEC_FLAG_MAXIMUM_ALLOWED,
2939                                                &hnd);
2940         if (!W_ERROR_IS_OK(result)) {
2941                 goto done;
2942         }
2943
2944         /* Set Job */
2945
2946         status = dcerpc_spoolss_SetJob(b, mem_ctx,
2947                                        &hnd,
2948                                        job_id,
2949                                        NULL,
2950                                        command,
2951                                        &result);
2952         if (!NT_STATUS_IS_OK(status)) {
2953                 result = ntstatus_to_werror(status);
2954                 goto done;
2955         }
2956         if (!W_ERROR_IS_OK(result)) {
2957                 goto done;
2958         }
2959
2960 done:
2961         if (is_valid_policy_hnd(&hnd)) {
2962                 WERROR _result;
2963                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2964         }
2965
2966         return result;
2967 }
2968
2969 /****************************************************************************
2970 ****************************************************************************/
2971
2972 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2973                                     TALLOC_CTX *mem_ctx, int argc,
2974                                     const char **argv)
2975 {
2976         WERROR result;
2977         NTSTATUS status;
2978         const char *printername;
2979         struct policy_handle hnd;
2980         uint32_t value_needed;
2981         enum winreg_Type type;
2982         uint32_t data_needed;
2983         struct dcerpc_binding_handle *b = cli->binding_handle;
2984         struct spoolss_EnumPrinterData r;
2985
2986         if (argc != 2) {
2987                 printf("Usage: %s printername\n", argv[0]);
2988                 return WERR_OK;
2989         }
2990
2991         /* Open printer handle */
2992
2993         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2994
2995         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2996                                                printername,
2997                                                SEC_FLAG_MAXIMUM_ALLOWED,
2998                                                &hnd);
2999         if (!W_ERROR_IS_OK(result)) {
3000                 goto done;
3001         }
3002
3003         /* Enumerate data */
3004
3005         r.in.handle = &hnd;
3006         r.in.enum_index = 0;
3007         r.in.value_offered = 0;
3008         r.in.data_offered = 0;
3009         r.out.value_name = NULL;
3010         r.out.value_needed = &value_needed;
3011         r.out.type = &type;
3012         r.out.data = NULL;
3013         r.out.data_needed = &data_needed;
3014
3015         status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3016         if (!NT_STATUS_IS_OK(status)) {
3017                 result = ntstatus_to_werror(status);
3018                 goto done;
3019         }
3020
3021         if (!W_ERROR_IS_OK(r.out.result)) {
3022                 result = r.out.result;
3023                 goto done;
3024         }
3025
3026         r.in.data_offered       = *r.out.data_needed;
3027         r.in.value_offered      = *r.out.value_needed;
3028         r.out.data              = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3029         r.out.value_name        = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3030
3031         do {
3032
3033                 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3034                 if (!NT_STATUS_IS_OK(status)) {
3035                         result = ntstatus_to_werror(status);
3036                         goto done;
3037                 }
3038
3039                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3040                         result = WERR_OK;
3041                         break;
3042                 }
3043
3044                 r.in.enum_index++;
3045
3046                 {
3047                         struct regval_blob *v;
3048
3049                         v = regval_compose(talloc_tos(),
3050                                            r.out.value_name,
3051                                            *r.out.type,
3052                                            r.out.data,
3053                                            r.in.data_offered);
3054                         if (v == NULL) {
3055                                 result = WERR_NOMEM;
3056                                 goto done;
3057                         }
3058
3059                         display_reg_value(v);
3060                         talloc_free(v);
3061                 }
3062
3063         } while (W_ERROR_IS_OK(r.out.result));
3064
3065 done:
3066         if (is_valid_policy_hnd(&hnd)) {
3067                 WERROR _result;
3068                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3069         }
3070
3071         return result;
3072 }
3073
3074 /****************************************************************************
3075 ****************************************************************************/
3076
3077 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3078                                           TALLOC_CTX *mem_ctx, int argc,
3079                                           const char **argv)
3080 {
3081         WERROR result;
3082         uint32_t i;
3083         const char *printername;
3084         struct policy_handle hnd;
3085         uint32_t count;
3086         struct spoolss_PrinterEnumValues *info;
3087         struct dcerpc_binding_handle *b = cli->binding_handle;
3088
3089         if (argc != 3) {
3090                 printf("Usage: %s printername <keyname>\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 subkeys */
3107
3108         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3109                                                   &hnd,
3110                                                   argv[2],
3111                                                   0,
3112                                                   &count,
3113                                                   &info);
3114         if (!W_ERROR_IS_OK(result)) {
3115                 goto done;
3116         }
3117
3118         for (i=0; i < count; i++) {
3119                 display_printer_data(info[i].value_name,
3120                                      info[i].type,
3121                                      info[i].data->data,
3122                                      info[i].data->length);
3123         }
3124
3125  done:
3126         if (is_valid_policy_hnd(&hnd)) {
3127                 WERROR _result;
3128                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3129         }
3130
3131         return result;
3132 }
3133
3134 /****************************************************************************
3135 ****************************************************************************/
3136
3137 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3138                                           TALLOC_CTX *mem_ctx, int argc,
3139                                           const char **argv)
3140 {
3141         WERROR result;
3142         const char *printername;
3143         const char *keyname = NULL;
3144         struct policy_handle hnd;
3145         const char **key_buffer = NULL;
3146         int i;
3147         uint32_t offered = 0;
3148         struct dcerpc_binding_handle *b = cli->binding_handle;
3149
3150         if (argc < 2 || argc > 4) {
3151                 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3152                 return WERR_OK;
3153         }
3154
3155         if (argc >= 3) {
3156                 keyname = argv[2];
3157         } else {
3158                 keyname = "";
3159         }
3160
3161         if (argc == 4) {
3162                 offered = atoi(argv[3]);
3163         }
3164
3165         /* Open printer handle */
3166
3167         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3168
3169         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3170                                                printername,
3171                                                SEC_FLAG_MAXIMUM_ALLOWED,
3172                                                &hnd);
3173         if (!W_ERROR_IS_OK(result)) {
3174                 goto done;
3175         }
3176
3177         /* Enumerate subkeys */
3178
3179         result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3180                                                &hnd,
3181                                                keyname,
3182                                                &key_buffer,
3183                                                offered);
3184
3185         if (!W_ERROR_IS_OK(result)) {
3186                 goto done;
3187         }
3188
3189         for (i=0; key_buffer && key_buffer[i]; i++) {
3190                 printf("%s\n", key_buffer[i]);
3191         }
3192
3193  done:
3194
3195         if (is_valid_policy_hnd(&hnd)) {
3196                 WERROR _result;
3197                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3198         }
3199
3200         return result;
3201 }
3202
3203 /****************************************************************************
3204 ****************************************************************************/
3205
3206 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3207                                      TALLOC_CTX *mem_ctx, int argc,
3208                                      const char **argv)
3209 {
3210         const char *printername;
3211         const char *clientname;
3212         struct policy_handle hnd;
3213         WERROR result;
3214         NTSTATUS status;
3215         struct spoolss_NotifyOption option;
3216         struct dcerpc_binding_handle *b = cli->binding_handle;
3217
3218         if (argc != 2) {
3219                 printf("Usage: %s printername\n", argv[0]);
3220                 result = WERR_OK;
3221                 goto done;
3222         }
3223
3224         /* Open printer */
3225
3226         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3227
3228         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3229                                                printername,
3230                                                SEC_FLAG_MAXIMUM_ALLOWED,
3231                                                &hnd);
3232         if (!W_ERROR_IS_OK(result)) {
3233                 printf("Error opening %s\n", argv[1]);
3234                 goto done;
3235         }
3236
3237         /* Create spool options */
3238
3239         option.version = 2;
3240         option.count = 2;
3241
3242         option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3243         if (option.types == NULL) {
3244                 result = WERR_NOMEM;
3245                 goto done;
3246         }
3247
3248         option.types[0].type = PRINTER_NOTIFY_TYPE;
3249         option.types[0].count = 1;
3250         option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3251         if (option.types[0].fields == NULL) {
3252                 result = WERR_NOMEM;
3253                 goto done;
3254         }
3255         option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3256
3257         option.types[1].type = JOB_NOTIFY_TYPE;
3258         option.types[1].count = 1;
3259         option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3260         if (option.types[1].fields == NULL) {
3261                 result = WERR_NOMEM;
3262                 goto done;
3263         }
3264         option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3265
3266         clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3267         if (!clientname) {
3268                 result = WERR_NOMEM;
3269                 goto done;
3270         }
3271
3272         /* Send rffpcnex */
3273
3274         status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3275                                                                      &hnd,
3276                                                                      0,
3277                                                                      0,
3278                                                                      clientname,
3279                                                                      123,
3280                                                                      &option,
3281                                                                      &result);
3282         if (!NT_STATUS_IS_OK(status)) {
3283                 result = ntstatus_to_werror(status);
3284                 goto done;
3285         }
3286         if (!W_ERROR_IS_OK(result)) {
3287                 printf("Error rffpcnex %s\n", argv[1]);
3288                 goto done;
3289         }
3290
3291 done:
3292         if (is_valid_policy_hnd(&hnd)) {
3293                 WERROR _result;
3294                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3295         }
3296
3297         return result;
3298 }
3299
3300 /****************************************************************************
3301 ****************************************************************************/
3302
3303 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3304                              struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3305 {
3306         union spoolss_PrinterInfo info1, info2;
3307         WERROR werror;
3308         TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3309
3310         printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3311         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3312                                            hnd1,
3313                                            2,
3314                                            0,
3315                                            &info1);
3316         if ( !W_ERROR_IS_OK(werror) ) {
3317                 printf("failed (%s)\n", win_errstr(werror));
3318                 talloc_destroy(mem_ctx);
3319                 return false;
3320         }
3321         printf("ok\n");
3322
3323         printf("Retrieving printer properties for %s...", cli2->desthost);
3324         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3325                                            hnd2,
3326                                            2,
3327                                            0,
3328                                            &info2);
3329         if ( !W_ERROR_IS_OK(werror) ) {
3330                 printf("failed (%s)\n", win_errstr(werror));
3331                 talloc_destroy(mem_ctx);
3332                 return false;
3333         }
3334         printf("ok\n");
3335
3336         talloc_destroy(mem_ctx);
3337
3338         return true;
3339 }
3340
3341 /****************************************************************************
3342 ****************************************************************************/
3343
3344 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3345                                      struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3346 {
3347         union spoolss_PrinterInfo info1, info2;
3348         WERROR werror;
3349         TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3350         struct security_descriptor *sd1, *sd2;
3351         bool result = true;
3352
3353
3354         printf("Retrieving printer security for %s...", cli1->desthost);
3355         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3356                                            hnd1,
3357                                            3,
3358                                            0,
3359                                            &info1);
3360         if ( !W_ERROR_IS_OK(werror) ) {
3361                 printf("failed (%s)\n", win_errstr(werror));
3362                 result = false;
3363                 goto done;
3364         }
3365         printf("ok\n");
3366
3367         printf("Retrieving printer security for %s...", cli2->desthost);
3368         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3369                                            hnd2,
3370                                            3,
3371                                            0,
3372                                            &info2);
3373         if ( !W_ERROR_IS_OK(werror) ) {
3374                 printf("failed (%s)\n", win_errstr(werror));
3375                 result = false;
3376                 goto done;
3377         }
3378         printf("ok\n");
3379
3380
3381         printf("++ ");
3382
3383         sd1 = info1.info3.secdesc;
3384         sd2 = info2.info3.secdesc;
3385
3386         if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3387                 printf("NULL secdesc!\n");
3388                 result = false;
3389                 goto done;
3390         }
3391
3392         if (!security_descriptor_equal( sd1, sd2 ) ) {
3393                 printf("Security Descriptors *not* equal!\n");
3394                 result = false;
3395                 goto done;
3396         }
3397
3398         printf("Security descriptors match\n");
3399
3400 done:
3401         talloc_destroy(mem_ctx);
3402         return result;
3403 }
3404
3405
3406 /****************************************************************************
3407 ****************************************************************************/
3408
3409 extern struct user_auth_info *rpcclient_auth_info;
3410
3411 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3412                                      TALLOC_CTX *mem_ctx, int argc,
3413                                      const char **argv)
3414 {
3415         const char *printername;
3416         char *printername_path = NULL;
3417         struct cli_state *cli_server2 = NULL;
3418         struct rpc_pipe_client *cli2 = NULL;
3419         struct policy_handle hPrinter1, hPrinter2;
3420         NTSTATUS nt_status;
3421         WERROR werror;
3422
3423         if ( argc != 3 )  {
3424                 printf("Usage: %s <printer> <server>\n", argv[0]);
3425                 return WERR_OK;
3426         }
3427
3428         printername = argv[1];
3429
3430         /* first get the connection to the remote server */
3431
3432         nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3433                                         NULL, 0,
3434                                         "IPC$", "IPC",
3435                                         get_cmdline_auth_info_username(rpcclient_auth_info),
3436                                         lp_workgroup(),
3437                                         get_cmdline_auth_info_password(rpcclient_auth_info),
3438                                         get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3439                                         get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3440
3441         if ( !NT_STATUS_IS_OK(nt_status) )
3442                 return WERR_GENERAL_FAILURE;
3443
3444         nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3445                                              &cli2);
3446         if (!NT_STATUS_IS_OK(nt_status)) {
3447                 printf("failed to open spoolss pipe on server %s (%s)\n",
3448                         argv[2], nt_errstr(nt_status));
3449                 return WERR_GENERAL_FAILURE;
3450         }
3451
3452         /* now open up both printers */
3453
3454         RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3455
3456         printf("Opening %s...", printername_path);
3457
3458         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3459                                                printername_path,
3460                                                PRINTER_ALL_ACCESS,
3461                                                &hPrinter1);
3462         if ( !W_ERROR_IS_OK(werror) ) {
3463                 printf("failed (%s)\n", win_errstr(werror));
3464                 goto done;
3465         }
3466         printf("ok\n");
3467
3468         RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3469
3470         printf("Opening %s...", printername_path);
3471         werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3472                                                printername_path,
3473                                                PRINTER_ALL_ACCESS,
3474                                                &hPrinter2);
3475         if ( !W_ERROR_IS_OK(werror) ) {
3476                  printf("failed (%s)\n", win_errstr(werror));
3477                 goto done;
3478         }
3479         printf("ok\n");
3480
3481         compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3482         compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3483 #if 0
3484         compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3485 #endif
3486
3487
3488 done:
3489         /* cleanup */
3490
3491         printf("Closing printers...");
3492         {
3493                 WERROR _result;
3494                 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3495                 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3496         }
3497         printf("ok\n");
3498
3499         /* close the second remote connection */
3500
3501         cli_shutdown( cli_server2 );
3502         return WERR_OK;
3503 }
3504
3505 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3506 {
3507         printf("print_processor_name: %s\n", r->print_processor_name);
3508 }
3509
3510 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3511                                      TALLOC_CTX *mem_ctx, int argc,
3512                                      const char **argv)
3513 {
3514         WERROR werror;
3515         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3516         uint32_t num_procs, level = 1, i;
3517         union spoolss_PrintProcessorInfo *procs;
3518
3519         /* Parse the command arguments */
3520
3521         if (argc < 1 || argc > 4) {
3522                 printf ("Usage: %s [environment] [level]\n", argv[0]);
3523                 return WERR_OK;
3524         }
3525
3526         if (argc >= 2) {
3527                 environment = argv[1];
3528         }
3529
3530         if (argc == 3) {
3531                 level = atoi(argv[2]);
3532         }
3533
3534         /* Enumerate Print Processors */
3535
3536         werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3537                                                     cli->srv_name_slash,
3538                                                     environment,
3539                                                     level,
3540                                                     0,
3541                                                     &num_procs,
3542                                                     &procs);
3543         if (!W_ERROR_IS_OK(werror))
3544                 goto done;
3545
3546         /* Display output */
3547
3548         for (i = 0; i < num_procs; i++) {
3549                 switch (level) {
3550                 case 1:
3551                         display_proc_info1(&procs[i].info1);
3552                         break;
3553                 }
3554         }
3555
3556  done:
3557         return werror;
3558 }
3559
3560 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3561 {
3562         printf("name_array: %s\n", r->name_array);
3563 }
3564
3565 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3566                                                TALLOC_CTX *mem_ctx, int argc,
3567                                                const char **argv)
3568 {
3569         WERROR werror;
3570         const char *print_processor_name = "winprint";
3571         uint32_t num_procs, level = 1, i;
3572         union spoolss_PrintProcDataTypesInfo *procs;
3573
3574         /* Parse the command arguments */
3575
3576         if (argc < 1 || argc > 4) {
3577                 printf ("Usage: %s [environment] [level]\n", argv[0]);
3578                 return WERR_OK;
3579         }
3580
3581         if (argc >= 2) {
3582                 print_processor_name = argv[1];
3583         }
3584
3585         if (argc == 3) {
3586                 level = atoi(argv[2]);
3587         }
3588
3589         /* Enumerate Print Processor Data Types */
3590
3591         werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3592                                                             cli->srv_name_slash,
3593                                                             print_processor_name,
3594                                                             level,
3595                                                             0,
3596                                                             &num_procs,
3597                                                             &procs);
3598         if (!W_ERROR_IS_OK(werror))
3599                 goto done;
3600
3601         /* Display output */
3602
3603         for (i = 0; i < num_procs; i++) {
3604                 switch (level) {
3605                 case 1:
3606                         display_proc_data_types_info1(&procs[i].info1);
3607                         break;
3608                 }
3609         }
3610
3611  done:
3612         return werror;
3613 }
3614
3615 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3616 {
3617         printf("monitor_name: %s\n", r->monitor_name);
3618 }
3619
3620 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3621 {
3622         printf("monitor_name: %s\n", r->monitor_name);
3623         printf("environment: %s\n", r->environment);
3624         printf("dll_name: %s\n", r->dll_name);
3625 }
3626
3627 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3628                                         TALLOC_CTX *mem_ctx, int argc,
3629                                         const char **argv)
3630 {
3631         WERROR werror;
3632         uint32_t count, level = 1, i;
3633         union spoolss_MonitorInfo *info;
3634
3635         /* Parse the command arguments */
3636
3637         if (argc > 2) {
3638                 printf("Usage: %s [level]\n", argv[0]);
3639                 return WERR_OK;
3640         }
3641
3642         if (argc == 2) {
3643                 level = atoi(argv[1]);
3644         }
3645
3646         /* Enumerate Print Monitors */
3647
3648         werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3649                                              cli->srv_name_slash,
3650                                              level,
3651                                              0,
3652                                              &count,
3653                                              &info);
3654         if (!W_ERROR_IS_OK(werror)) {
3655                 goto done;
3656         }
3657
3658         /* Display output */
3659
3660         for (i = 0; i < count; i++) {
3661                 switch (level) {
3662                 case 1:
3663                         display_monitor1(&info[i].info1);
3664                         break;
3665                 case 2:
3666                         display_monitor2(&info[i].info2);
3667                         break;
3668                 }
3669         }
3670
3671  done:
3672         return werror;
3673 }
3674
3675 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3676                                             TALLOC_CTX *mem_ctx, int argc,
3677                                             const char **argv)
3678 {
3679         WERROR result;
3680         NTSTATUS status;
3681         struct policy_handle handle, gdi_handle;
3682         const char *printername;
3683         struct spoolss_DevmodeContainer devmode_ctr;
3684         struct dcerpc_binding_handle *b = cli->binding_handle;
3685
3686         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3687
3688         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3689                                                printername,
3690                                                SEC_FLAG_MAXIMUM_ALLOWED,
3691                                                &handle);
3692         if (!W_ERROR_IS_OK(result)) {
3693                 return result;
3694         }
3695
3696         ZERO_STRUCT(devmode_ctr);
3697
3698         status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3699                                                 &handle,
3700                                                 &gdi_handle,
3701                                                 &devmode_ctr,
3702                                                 &result);
3703         if (!NT_STATUS_IS_OK(status)) {
3704                 result = ntstatus_to_werror(status);
3705                 goto done;
3706         }
3707         if (!W_ERROR_IS_OK(result)) {
3708                 goto done;
3709         }
3710
3711  done:
3712         if (is_valid_policy_hnd(&gdi_handle)) {
3713                 WERROR _result;
3714                 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3715         }
3716         if (is_valid_policy_hnd(&handle)) {
3717                 WERROR _result;
3718                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3719         }
3720
3721         return result;
3722 }
3723
3724 /* List of commands exported by this module */
3725 struct cmd_set spoolss_commands[] = {
3726
3727         { "SPOOLSS"  },
3728
3729         { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &ndr_table_spoolss.syntax_id, NULL, "Add a print driver",                  "" },
3730         { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &ndr_table_spoolss.syntax_id, NULL, "Add a printer",                       "" },
3731         { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver",             "" },
3732         { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files",  "" },
3733         { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data",              "" },
3734         { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key",    "" },
3735         { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys",              "" },
3736         { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs",                "" },
3737         { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &ndr_table_spoolss.syntax_id, NULL, "Get print job",                       "" },
3738         { "setjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job,            &ndr_table_spoolss.syntax_id, NULL, "Set print job",                       "" },
3739         { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports",             "" },
3740         { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3741         { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers",                  "" },
3742         { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &ndr_table_spoolss.syntax_id, NULL, "Get print driver data",               "" },
3743         { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3744         { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &ndr_table_spoolss.syntax_id, NULL, "Get print driver information",        "" },
3745         { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory",   "" },
3746         { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &ndr_table_spoolss.syntax_id, NULL, "Get printer info",                    "" },
3747         { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer,       &ndr_table_spoolss.syntax_id, NULL, "Open printer handle",                 "" },
3748         { "openprinter_ex",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &ndr_table_spoolss.syntax_id, NULL, "Open printer handle",                 "" },
3749         { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &ndr_table_spoolss.syntax_id, NULL, "Set printer driver",                  "" },
3750         { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory",       "" },
3751         { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &ndr_table_spoolss.syntax_id, NULL, "Add form",                            "" },
3752         { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &ndr_table_spoolss.syntax_id, NULL, "Set form",                            "" },
3753         { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &ndr_table_spoolss.syntax_id, NULL, "Get form",                            "" },
3754         { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &ndr_table_spoolss.syntax_id, NULL, "Delete form",                         "" },
3755         { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms",                     "" },
3756         { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &ndr_table_spoolss.syntax_id, NULL, "Set printer comment",                 "" },
3757         { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &ndr_table_spoolss.syntax_id, NULL, "Set printername",                 "" },
3758         { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data",             "" },
3759         { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3760         { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3761         { "enumprocs",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors",          "" },
3762         { "enumprocdatatypes",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3763         { "enummonitors",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors,      &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3764         { "createprinteric",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic,  &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3765
3766         { NULL }
3767 };