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