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