s3-rpcclient: fix cmd_spoolss_getprinterdataex.
[kamenim/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                 for (i=0; i<num_values; i++) {
686                         d_printf("%s\n", values[i]);
687                 }
688                 TALLOC_FREE(values);
689                 break;
690         }
691         default:
692                 printf("%s: unknown type %d\n", value.valuename, value.type);
693         }
694
695 }
696
697 /****************************************************************************
698 ****************************************************************************/
699
700 static void display_printer_data(const char *v,
701                                  enum winreg_Type type,
702                                  union spoolss_PrinterData *r)
703 {
704         int i;
705
706         switch (type) {
707         case REG_DWORD:
708                 printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
709                 break;
710         case REG_SZ:
711                 printf("%s: REG_SZ: %s\n", v, r->string);
712                 break;
713         case REG_BINARY: {
714                 char *hex = hex_encode_talloc(NULL,
715                         r->binary.data, r->binary.length);
716                 size_t len;
717                 printf("%s: REG_BINARY:", v);
718                 len = strlen(hex);
719                 for (i=0; i<len; i++) {
720                         if (hex[i] == '\0') {
721                                 break;
722                         }
723                         if (i%40 == 0) {
724                                 putchar('\n');
725                         }
726                         putchar(hex[i]);
727                 }
728                 TALLOC_FREE(hex);
729                 putchar('\n');
730                 break;
731         }
732         case REG_MULTI_SZ:
733                 printf("%s: REG_MULTI_SZ: ", v);
734                 for (i=0; r->string_array[i] != NULL; i++) {
735                         printf("%s ", r->string_array[i]);
736                 }
737                 printf("\n");
738                 break;
739         default:
740                 printf("%s: unknown type 0x%02x:\n", v, type);
741                 break;
742         }
743 }
744
745 /****************************************************************************
746 ****************************************************************************/
747
748 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
749                                            TALLOC_CTX *mem_ctx,
750                                            int argc, const char **argv)
751 {
752         POLICY_HND      pol;
753         WERROR          result;
754         fstring         printername;
755         const char *valuename;
756         enum winreg_Type type;
757         union spoolss_PrinterData data;
758
759         if (argc != 3) {
760                 printf("Usage: %s <printername> <valuename>\n", argv[0]);
761                 printf("<printername> of . queries print server\n");
762                 return WERR_OK;
763         }
764         valuename = argv[2];
765
766         /* Open a printer handle */
767
768         if (strncmp(argv[1], ".", sizeof(".")) == 0)
769                 fstrcpy(printername, cli->srv_name_slash);
770         else
771                 slprintf(printername, sizeof(printername)-1, "%s\\%s",
772                           cli->srv_name_slash, argv[1]);
773
774         /* get a printer handle */
775
776         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
777                                                printername,
778                                                SEC_FLAG_MAXIMUM_ALLOWED,
779                                                &pol);
780         if (!W_ERROR_IS_OK(result))
781                 goto done;
782
783         /* Get printer info */
784
785         result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
786                                                &pol,
787                                                valuename,
788                                                0,
789                                                &type,
790                                                &data);
791         if (!W_ERROR_IS_OK(result))
792                 goto done;
793
794         /* Display printer data */
795
796         display_printer_data(valuename, type, &data);
797
798  done:
799         if (is_valid_policy_hnd(&pol))
800                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
801
802         return result;
803 }
804
805 /****************************************************************************
806 ****************************************************************************/
807
808 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
809                                              TALLOC_CTX *mem_ctx,
810                                              int argc, const char **argv)
811 {
812         POLICY_HND      pol;
813         WERROR          result;
814         NTSTATUS        status;
815         fstring         printername;
816         const char *valuename, *keyname;
817         REGISTRY_VALUE value;
818
819         enum winreg_Type type;
820         uint8_t *buffer = NULL;
821         uint32_t offered = 0;
822         uint32_t needed;
823
824         if (argc != 4) {
825                 printf("Usage: %s <printername> <keyname> <valuename>\n",
826                        argv[0]);
827                 printf("<printername> of . queries print server\n");
828                 return WERR_OK;
829         }
830         valuename = argv[3];
831         keyname = argv[2];
832
833         /* Open a printer handle */
834
835         if (strncmp(argv[1], ".", sizeof(".")) == 0)
836                 fstrcpy(printername, cli->srv_name_slash);
837         else
838                 slprintf(printername, sizeof(printername)-1, "%s\\%s",
839                           cli->srv_name_slash, argv[1]);
840
841         /* get a printer handle */
842
843         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
844                                                printername,
845                                                SEC_FLAG_MAXIMUM_ALLOWED,
846                                                &pol);
847         if (!W_ERROR_IS_OK(result))
848                 goto done;
849
850         /* Get printer info */
851
852         status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
853                                                  &pol,
854                                                  keyname,
855                                                  valuename,
856                                                  &type,
857                                                  buffer,
858                                                  offered,
859                                                  &needed,
860                                                  &result);
861         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
862                 offered = needed;
863                 buffer = talloc_array(mem_ctx, uint8_t, needed);
864                 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
865                                                          &pol,
866                                                          keyname,
867                                                          valuename,
868                                                          &type,
869                                                          buffer,
870                                                          offered,
871                                                          &needed,
872                                                          &result);
873         }
874
875         if (!NT_STATUS_IS_OK(status)) {
876                 goto done;
877         }
878
879         if (!W_ERROR_IS_OK(result)) {
880                 goto done;
881         }
882
883
884         if (!W_ERROR_IS_OK(result))
885                 goto done;
886
887         /* Display printer data */
888
889         fstrcpy(value.valuename, valuename);
890         value.type = type;
891         value.size = needed;
892         value.data_p = buffer;
893
894         display_reg_value(value);
895
896  done:
897         if (is_valid_policy_hnd(&pol))
898                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
899
900         return result;
901 }
902
903 /****************************************************************************
904 ****************************************************************************/
905
906 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
907 {
908         if (!r) {
909                 return;
910         }
911
912         printf("Printer Driver Info 1:\n");
913         printf("\tDriver Name: [%s]\n\n", r->driver_name);
914 }
915
916 /****************************************************************************
917 ****************************************************************************/
918
919 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
920 {
921         if (!r) {
922                 return;
923         }
924
925         printf("Printer Driver Info 2:\n");
926         printf("\tVersion: [%x]\n", r->version);
927         printf("\tDriver Name: [%s]\n", r->driver_name);
928         printf("\tArchitecture: [%s]\n", r->architecture);
929         printf("\tDriver Path: [%s]\n", r->driver_path);
930         printf("\tDatafile: [%s]\n", r->data_file);
931         printf("\tConfigfile: [%s]\n\n", r->config_file);
932 }
933
934 /****************************************************************************
935 ****************************************************************************/
936
937 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
938 {
939         int i;
940
941         if (!r) {
942                 return;
943         }
944
945         printf("Printer Driver Info 3:\n");
946         printf("\tVersion: [%x]\n", r->version);
947         printf("\tDriver Name: [%s]\n", r->driver_name);
948         printf("\tArchitecture: [%s]\n", r->architecture);
949         printf("\tDriver Path: [%s]\n", r->driver_path);
950         printf("\tDatafile: [%s]\n", r->data_file);
951         printf("\tConfigfile: [%s]\n\n", r->config_file);
952         printf("\tHelpfile: [%s]\n\n", r->help_file);
953
954         for (i=0; r->dependent_files[i] != NULL; i++) {
955                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
956         }
957
958         printf("\n");
959
960         printf("\tMonitorname: [%s]\n", r->monitor_name);
961         printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
962 }
963
964
965 /****************************************************************************
966 ****************************************************************************/
967
968 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
969                                     TALLOC_CTX *mem_ctx,
970                                     int argc, const char **argv)
971 {
972         POLICY_HND      pol;
973         WERROR          werror;
974         uint32_t        level = 3;
975         const char      *printername;
976         uint32_t        i;
977         bool            success = false;
978         union spoolss_DriverInfo info;
979         uint32_t server_major_version;
980         uint32_t server_minor_version;
981
982         if ((argc == 1) || (argc > 3)) {
983                 printf("Usage: %s <printername> [level]\n", argv[0]);
984                 return WERR_OK;
985         }
986
987         /* get the arguments need to open the printer handle */
988
989         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
990
991         if (argc == 3) {
992                 level = atoi(argv[2]);
993         }
994
995         /* Open a printer handle */
996
997         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
998                                                printername,
999                                                PRINTER_ACCESS_USE,
1000                                                &pol);
1001         if (!W_ERROR_IS_OK(werror)) {
1002                 printf("Error opening printer handle for %s!\n", printername);
1003                 return werror;
1004         }
1005
1006         /* loop through and print driver info level for each architecture */
1007
1008         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1009
1010                 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1011                                                           &pol,
1012                                                           archi_table[i].long_archi,
1013                                                           level,
1014                                                           0, /* offered */
1015                                                           archi_table[i].version,
1016                                                           2,
1017                                                           &info,
1018                                                           &server_major_version,
1019                                                           &server_minor_version);
1020                 if (!W_ERROR_IS_OK(werror)) {
1021                         continue;
1022                 }
1023
1024                 /* need at least one success */
1025
1026                 success = true;
1027
1028                 printf("\n[%s]\n", archi_table[i].long_archi);
1029
1030                 switch (level) {
1031                 case 1:
1032                         display_print_driver1(&info.info1);
1033                         break;
1034                 case 2:
1035                         display_print_driver2(&info.info2);
1036                         break;
1037                 case 3:
1038                         display_print_driver3(&info.info3);
1039                         break;
1040                 default:
1041                         printf("unknown info level %d\n", level);
1042                         break;
1043                 }
1044         }
1045
1046         /* Cleanup */
1047
1048         if (is_valid_policy_hnd(&pol)) {
1049                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1050         }
1051
1052         if (success) {
1053                 werror = WERR_OK;
1054         }
1055
1056         return werror;
1057 }
1058
1059 /****************************************************************************
1060 ****************************************************************************/
1061
1062 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1063                                          TALLOC_CTX *mem_ctx,
1064                                          int argc, const char **argv)
1065 {
1066         WERROR werror = WERR_OK;
1067         uint32_t        level = 1;
1068         union spoolss_DriverInfo *info;
1069         uint32_t        i, j, count;
1070
1071         if (argc > 2) {
1072                 printf("Usage: enumdrivers [level]\n");
1073                 return WERR_OK;
1074         }
1075
1076         if (argc == 2) {
1077                 level = atoi(argv[1]);
1078         }
1079
1080
1081         /* loop through and print driver info level for each architecture */
1082         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1083                 /* check to see if we already asked for this architecture string */
1084
1085                 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1086                         continue;
1087                 }
1088
1089                 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1090                                                            cli->srv_name_slash,
1091                                                            archi_table[i].long_archi,
1092                                                            level,
1093                                                            0,
1094                                                            &count,
1095                                                            &info);
1096
1097                 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1098                         printf("Server does not support environment [%s]\n",
1099                                 archi_table[i].long_archi);
1100                         werror = WERR_OK;
1101                         continue;
1102                 }
1103
1104                 if (count == 0) {
1105                         continue;
1106                 }
1107
1108                 if (!W_ERROR_IS_OK(werror)) {
1109                         printf("Error getting driver for environment [%s] - %d\n",
1110                                 archi_table[i].long_archi, W_ERROR_V(werror));
1111                         continue;
1112                 }
1113
1114                 printf("\n[%s]\n", archi_table[i].long_archi);
1115
1116                 switch (level) {
1117                 case 1:
1118                         for (j=0; j < count; j++) {
1119                                 display_print_driver1(&info[j].info1);
1120                         }
1121                         break;
1122                 case 2:
1123                         for (j=0; j < count; j++) {
1124                                 display_print_driver2(&info[j].info2);
1125                         }
1126                         break;
1127                 case 3:
1128                         for (j=0; j < count; j++) {
1129                                 display_print_driver3(&info[j].info3);
1130                         }
1131                         break;
1132                 default:
1133                         printf("unknown info level %d\n", level);
1134                         return WERR_UNKNOWN_LEVEL;
1135                 }
1136         }
1137
1138         return werror;
1139 }
1140
1141 /****************************************************************************
1142 ****************************************************************************/
1143
1144 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1145 {
1146         printf("\tDirectory Name:[%s]\n", r->directory_name);
1147 }
1148
1149 /****************************************************************************
1150 ****************************************************************************/
1151
1152 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1153                                          TALLOC_CTX *mem_ctx,
1154                                          int argc, const char **argv)
1155 {
1156         WERROR result;
1157         NTSTATUS status;
1158         const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1159         DATA_BLOB buffer;
1160         uint32_t offered;
1161         union spoolss_DriverDirectoryInfo info;
1162         uint32_t needed;
1163
1164         if (argc > 2) {
1165                 printf("Usage: %s [environment]\n", argv[0]);
1166                 return WERR_OK;
1167         }
1168
1169         /* Get the arguments need to open the printer handle */
1170
1171         if (argc == 2) {
1172                 env = argv[1];
1173         }
1174
1175         /* Get the directory.  Only use Info level 1 */
1176
1177         status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1178                                                           cli->srv_name_slash,
1179                                                           env,
1180                                                           1,
1181                                                           NULL, /* buffer */
1182                                                           0, /* offered */
1183                                                           NULL, /* info */
1184                                                           &needed,
1185                                                           &result);
1186         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1187                 offered = needed;
1188                 buffer = data_blob_talloc_zero(mem_ctx, needed);
1189
1190                 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1191                                                                   cli->srv_name_slash,
1192                                                                   env,
1193                                                                   1,
1194                                                                   &buffer,
1195                                                                   offered,
1196                                                                   &info,
1197                                                                   &needed,
1198                                                                   &result);
1199         }
1200
1201         if (W_ERROR_IS_OK(result)) {
1202                 display_printdriverdir_1(&info.info1);
1203         }
1204
1205         return result;
1206 }
1207
1208 /****************************************************************************
1209 ****************************************************************************/
1210
1211 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1212                                struct spoolss_AddDriverInfo3 *info,
1213                                const char *arch)
1214 {
1215
1216         int i;
1217
1218         for (i=0; archi_table[i].long_archi != NULL; i++)
1219         {
1220                 if (strcmp(arch, archi_table[i].short_archi) == 0)
1221                 {
1222                         info->version = archi_table[i].version;
1223                         info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1224                         break;
1225                 }
1226         }
1227
1228         if (archi_table[i].long_archi == NULL)
1229         {
1230                 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1231         }
1232
1233         return;
1234 }
1235
1236
1237 /**************************************************************************
1238  wrapper for strtok to get the next parameter from a delimited list.
1239  Needed to handle the empty parameter string denoted by "NULL"
1240  *************************************************************************/
1241
1242 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1243                                 const char *delim, const char **dest,
1244                                 char **saveptr)
1245 {
1246         char    *ptr;
1247
1248         /* get the next token */
1249         ptr = strtok_r(str, delim, saveptr);
1250
1251         /* a string of 'NULL' is used to represent an empty
1252            parameter because two consecutive delimiters
1253            will not return an empty string.  See man strtok(3)
1254            for details */
1255         if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1256                 ptr = NULL;
1257         }
1258
1259         if (dest != NULL) {
1260                 *dest = talloc_strdup(mem_ctx, ptr);
1261         }
1262
1263         return ptr;
1264 }
1265
1266 /********************************************************************************
1267  fill in the members of a spoolss_AddDriverInfo3 struct using a character
1268  string in the form of
1269          <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1270              <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1271              <Default Data Type>:<Comma Separated list of Files>
1272  *******************************************************************************/
1273
1274 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1275                                     char *args)
1276 {
1277         char    *str, *str2;
1278         int count = 0;
1279         char *saveptr = NULL;
1280         struct spoolss_StringArray *deps;
1281         const char **file_array = NULL;
1282         int i;
1283
1284         /* fill in the UNISTR fields */
1285         str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1286         str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1287         str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1288         str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1289         str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1290         str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1291         str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1292
1293         /* <Comma Separated List of Dependent Files> */
1294         /* save the beginning of the string */
1295         str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1296         str = str2;
1297
1298         /* begin to strip out each filename */
1299         str = strtok_r(str, ",", &saveptr);
1300
1301         /* no dependent files, we are done */
1302         if (!str) {
1303                 return true;
1304         }
1305
1306         deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1307         if (!deps) {
1308                 return false;
1309         }
1310
1311         while (str != NULL) {
1312                 add_string_to_array(deps, str, &file_array, &count);
1313                 str = strtok_r(NULL, ",", &saveptr);
1314         }
1315
1316         deps->string = talloc_zero_array(deps, const char *, count + 1);
1317         if (!deps->string) {
1318                 return false;
1319         }
1320
1321         for (i=0; i < count; i++) {
1322                 deps->string[i] = file_array[i];
1323         }
1324
1325         r->dependent_files = deps;
1326
1327         return true;
1328 }
1329
1330 /****************************************************************************
1331 ****************************************************************************/
1332
1333 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1334                                              TALLOC_CTX *mem_ctx,
1335                                              int argc, const char **argv)
1336 {
1337         WERROR result;
1338         NTSTATUS status;
1339         uint32                  level = 3;
1340         struct spoolss_AddDriverInfoCtr info_ctr;
1341         struct spoolss_AddDriverInfo3 info3;
1342         const char              *arch;
1343         char                    *driver_args;
1344
1345         /* parse the command arguments */
1346         if (argc != 3 && argc != 4)
1347         {
1348                 printf ("Usage: %s <Environment> \\\n", argv[0]);
1349                 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1350                 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1351                 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1352                 printf ("\t[version]\n");
1353
1354             return WERR_OK;
1355         }
1356
1357         /* Fill in the spoolss_AddDriverInfo3 struct */
1358         ZERO_STRUCT(info3);
1359
1360         arch = cmd_spoolss_get_short_archi(argv[1]);
1361         if (!arch) {
1362                 printf ("Error Unknown architechture [%s]\n", argv[1]);
1363                 return WERR_INVALID_PARAM;
1364         }
1365
1366         set_drv_info_3_env(mem_ctx, &info3, arch);
1367
1368         driver_args = talloc_strdup( mem_ctx, argv[2] );
1369         if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1370         {
1371                 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1372                 return WERR_INVALID_PARAM;
1373         }
1374
1375         /* if printer driver version specified, override the default version
1376          * used by the architecture.  This allows installation of Windows
1377          * 2000 (version 3) printer drivers. */
1378         if (argc == 4)
1379         {
1380                 info3.version = atoi(argv[3]);
1381         }
1382
1383
1384         info_ctr.level          = level;
1385         info_ctr.info.info3     = &info3;
1386
1387         status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1388                                                  cli->srv_name_slash,
1389                                                  &info_ctr,
1390                                                  &result);
1391         if (!NT_STATUS_IS_OK(status)) {
1392                 return ntstatus_to_werror(status);
1393         }
1394         if (W_ERROR_IS_OK(result)) {
1395                 printf ("Printer Driver %s successfully installed.\n",
1396                         info3.driver_name);
1397         }
1398
1399         return result;
1400 }
1401
1402
1403 /****************************************************************************
1404 ****************************************************************************/
1405
1406 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1407                                          TALLOC_CTX *mem_ctx,
1408                                          int argc, const char **argv)
1409 {
1410         WERROR result;
1411         struct spoolss_SetPrinterInfoCtr info_ctr;
1412         struct spoolss_SetPrinterInfo2 info2;
1413
1414         /* parse the command arguments */
1415         if (argc != 5)
1416         {
1417                 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1418                 return WERR_OK;
1419         }
1420
1421         /* Fill in the DRIVER_INFO_2 struct */
1422         ZERO_STRUCT(info2);
1423
1424         info2.printername       = argv[1];
1425         info2.drivername        = argv[3];
1426         info2.sharename         = argv[2];
1427         info2.portname          = argv[4];
1428         info2.comment           = "Created by rpcclient";
1429         info2.printprocessor    = "winprint";
1430         info2.datatype          = "RAW";
1431         info2.devmode           = NULL;
1432         info2.secdesc           = NULL;
1433         info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
1434         info2.priority          = 0;
1435         info2.defaultpriority   = 0;
1436         info2.starttime         = 0;
1437         info2.untiltime         = 0;
1438
1439         /* These three fields must not be used by AddPrinter()
1440            as defined in the MS Platform SDK documentation..
1441            --jerry
1442         info2.status            = 0;
1443         info2.cjobs             = 0;
1444         info2.averageppm        = 0;
1445         */
1446
1447         info_ctr.level = 2;
1448         info_ctr.info.info2 = &info2;
1449
1450         result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1451                                              &info_ctr);
1452         if (W_ERROR_IS_OK(result))
1453                 printf ("Printer %s successfully installed.\n", argv[1]);
1454
1455         return result;
1456 }
1457
1458 /****************************************************************************
1459 ****************************************************************************/
1460
1461 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1462                                       TALLOC_CTX *mem_ctx,
1463                                       int argc, const char **argv)
1464 {
1465         POLICY_HND              pol;
1466         WERROR                  result;
1467         NTSTATUS                status;
1468         uint32                  level = 2;
1469         const char              *printername;
1470         union spoolss_PrinterInfo info;
1471         struct spoolss_SetPrinterInfoCtr info_ctr;
1472         struct spoolss_DevmodeContainer devmode_ctr;
1473         struct sec_desc_buf secdesc_ctr;
1474
1475         ZERO_STRUCT(devmode_ctr);
1476         ZERO_STRUCT(secdesc_ctr);
1477
1478         /* parse the command arguments */
1479         if (argc != 3)
1480         {
1481                 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1482                 return WERR_OK;
1483         }
1484
1485         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1486
1487         /* Get a printer handle */
1488
1489         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1490                                                printername,
1491                                                PRINTER_ALL_ACCESS,
1492                                                &pol);
1493         if (!W_ERROR_IS_OK(result))
1494                 goto done;
1495
1496         /* Get printer info */
1497
1498         result = rpccli_spoolss_getprinter(cli, mem_ctx,
1499                                            &pol,
1500                                            level,
1501                                            0,
1502                                            &info);
1503         if (!W_ERROR_IS_OK(result)) {
1504                 printf ("Unable to retrieve printer information!\n");
1505                 goto done;
1506         }
1507
1508         /* Set the printer driver */
1509
1510         info.info2.drivername = argv[2];
1511         info.info2.devmode = NULL;
1512         info.info2.secdesc = NULL;
1513
1514         info_ctr.level = 2;
1515         info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1516
1517         status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1518                                            &pol,
1519                                            &info_ctr,
1520                                            &devmode_ctr,
1521                                            &secdesc_ctr,
1522                                            0, /* command */
1523                                            &result);
1524         if (!W_ERROR_IS_OK(result)) {
1525                 printf("SetPrinter call failed!\n");
1526                 goto done;;
1527         }
1528
1529         printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1530
1531 done:
1532         /* Cleanup */
1533
1534         if (is_valid_policy_hnd(&pol))
1535                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1536
1537         return result;
1538 }
1539
1540
1541 /****************************************************************************
1542 ****************************************************************************/
1543
1544 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1545                                          TALLOC_CTX *mem_ctx,
1546                                          int argc, const char **argv)
1547 {
1548         WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1549         NTSTATUS status;
1550
1551         int   i;
1552         int vers = -1;
1553
1554         const char *arch = NULL;
1555         uint32_t delete_flags = 0;
1556
1557         /* parse the command arguments */
1558         if (argc < 2 || argc > 4) {
1559                 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1560                 return WERR_OK;
1561         }
1562
1563         if (argc >= 3)
1564                 arch = argv[2];
1565         if (argc == 4)
1566                 vers = atoi (argv[3]);
1567
1568         if (vers >= 0) {
1569                 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1570         }
1571
1572         /* delete the driver for all architectures */
1573         for (i=0; archi_table[i].long_archi; i++) {
1574
1575                 if (arch &&  !strequal( archi_table[i].long_archi, arch))
1576                         continue;
1577
1578                 if (vers >= 0 && archi_table[i].version != vers)
1579                         continue;
1580
1581                 /* make the call to remove the driver */
1582                 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1583                                                               cli->srv_name_slash,
1584                                                               archi_table[i].long_archi,
1585                                                               argv[1],
1586                                                               delete_flags,
1587                                                               archi_table[i].version,
1588                                                               &result);
1589
1590                 if ( !W_ERROR_IS_OK(result) )
1591                 {
1592                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1593                                 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1594                                         argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1595                         }
1596                 }
1597                 else
1598                 {
1599                         printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1600                         archi_table[i].long_archi, archi_table[i].version);
1601                         ret = WERR_OK;
1602                 }
1603         }
1604
1605         return ret;
1606 }
1607
1608
1609 /****************************************************************************
1610 ****************************************************************************/
1611
1612 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1613                                          TALLOC_CTX *mem_ctx,
1614                                          int argc, const char **argv)
1615 {
1616         WERROR result = WERR_OK;
1617         NTSTATUS status;
1618         int                     i;
1619
1620         /* parse the command arguments */
1621         if (argc != 2) {
1622                 printf ("Usage: %s <driver>\n", argv[0]);
1623                 return WERR_OK;
1624         }
1625
1626         /* delete the driver for all architectures */
1627         for (i=0; archi_table[i].long_archi; i++) {
1628                 /* make the call to remove the driver */
1629                 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1630                                                             cli->srv_name_slash,
1631                                                             archi_table[i].long_archi,
1632                                                             argv[1],
1633                                                             &result);
1634                 if (!NT_STATUS_IS_OK(status)) {
1635                         return result;
1636                 }
1637                 if ( !W_ERROR_IS_OK(result) ) {
1638                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1639                                 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1640                                         argv[1], archi_table[i].long_archi,
1641                                         W_ERROR_V(result));
1642                         }
1643                 } else {
1644                         printf ("Driver %s removed for arch [%s].\n", argv[1],
1645                                 archi_table[i].long_archi);
1646                 }
1647         }
1648
1649         return result;
1650 }
1651
1652 /****************************************************************************
1653 ****************************************************************************/
1654
1655 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1656                                             TALLOC_CTX *mem_ctx,
1657                                             int argc, const char **argv)
1658 {
1659         WERROR result;
1660         NTSTATUS status;
1661         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1662         DATA_BLOB buffer;
1663         uint32_t offered;
1664         union spoolss_PrintProcessorDirectoryInfo info;
1665         uint32_t needed;
1666
1667         /* parse the command arguments */
1668         if (argc > 2) {
1669                 printf ("Usage: %s [environment]\n", argv[0]);
1670                 return WERR_OK;
1671         }
1672
1673         if (argc == 2) {
1674                 environment = argv[1];
1675         }
1676
1677         status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1678                                                            cli->srv_name_slash,
1679                                                            environment,
1680                                                            1,
1681                                                            NULL, /* buffer */
1682                                                            0, /* offered */
1683                                                            NULL, /* info */
1684                                                            &needed,
1685                                                            &result);
1686         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1687                 offered = needed;
1688                 buffer = data_blob_talloc_zero(mem_ctx, needed);
1689
1690                 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1691                                                                    cli->srv_name_slash,
1692                                                                    environment,
1693                                                                    1,
1694                                                                    &buffer,
1695                                                                    offered,
1696                                                                    &info,
1697                                                                    &needed,
1698                                                                    &result);
1699         }
1700
1701         if (W_ERROR_IS_OK(result)) {
1702                 printf("%s\n", info.info1.directory_name);
1703         }
1704
1705         return result;
1706 }
1707
1708 /****************************************************************************
1709 ****************************************************************************/
1710
1711 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1712                                     int argc, const char **argv)
1713 {
1714         POLICY_HND handle;
1715         WERROR werror;
1716         NTSTATUS status;
1717         const char *printername;
1718         union spoolss_AddFormInfo info;
1719         struct spoolss_AddFormInfo1 info1;
1720         struct spoolss_AddFormInfo2 info2;
1721         uint32_t level = 1;
1722
1723         /* Parse the command arguments */
1724
1725         if (argc < 3 || argc > 5) {
1726                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1727                 return WERR_OK;
1728         }
1729
1730         /* Get a printer handle */
1731
1732         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1733
1734         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1735                                                printername,
1736                                                PRINTER_ALL_ACCESS,
1737                                                &handle);
1738         if (!W_ERROR_IS_OK(werror))
1739                 goto done;
1740
1741         /* Dummy up some values for the form data */
1742
1743         if (argc == 4) {
1744                 level = atoi(argv[3]);
1745         }
1746
1747         switch (level) {
1748         case 1:
1749                 info1.flags             = SPOOLSS_FORM_USER;
1750                 info1.form_name         = argv[2];
1751                 info1.size.width        = 100;
1752                 info1.size.height       = 100;
1753                 info1.area.left         = 0;
1754                 info1.area.top          = 10;
1755                 info1.area.right        = 20;
1756                 info1.area.bottom       = 30;
1757
1758                 info.info1 = &info1;
1759
1760                 break;
1761         case 2:
1762                 info2.flags             = SPOOLSS_FORM_USER;
1763                 info2.form_name         = argv[2];
1764                 info2.size.width        = 100;
1765                 info2.size.height       = 100;
1766                 info2.area.left         = 0;
1767                 info2.area.top          = 10;
1768                 info2.area.right        = 20;
1769                 info2.area.bottom       = 30;
1770                 info2.keyword           = argv[2];
1771                 info2.string_type       = SPOOLSS_FORM_STRING_TYPE_NONE;
1772                 info2.mui_dll           = NULL;
1773                 info2.ressource_id      = 0;
1774                 info2.display_name      = argv[2];
1775                 info2.lang_id           = 0;
1776
1777                 info.info2 = &info2;
1778
1779                 break;
1780         }
1781
1782         /* Add the form */
1783
1784
1785         status = rpccli_spoolss_AddForm(cli, mem_ctx,
1786                                         &handle,
1787                                         level,
1788                                         info,
1789                                         &werror);
1790
1791  done:
1792         if (is_valid_policy_hnd(&handle))
1793                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1794
1795         return werror;
1796 }
1797
1798 /****************************************************************************
1799 ****************************************************************************/
1800
1801 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1802                                     int argc, const char **argv)
1803 {
1804         POLICY_HND handle;
1805         WERROR werror;
1806         NTSTATUS status;
1807         const char *printername;
1808         union spoolss_AddFormInfo info;
1809         struct spoolss_AddFormInfo1 info1;
1810
1811         /* Parse the command arguments */
1812
1813         if (argc != 3) {
1814                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1815                 return WERR_OK;
1816         }
1817
1818         /* Get a printer handle */
1819
1820         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1821
1822         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1823                                                printername,
1824                                                SEC_FLAG_MAXIMUM_ALLOWED,
1825                                                &handle);
1826         if (!W_ERROR_IS_OK(werror))
1827                 goto done;
1828
1829         /* Dummy up some values for the form data */
1830
1831         info1.flags             = SPOOLSS_FORM_PRINTER;
1832         info1.size.width        = 100;
1833         info1.size.height       = 100;
1834         info1.area.left         = 0;
1835         info1.area.top          = 1000;
1836         info1.area.right        = 2000;
1837         info1.area.bottom       = 3000;
1838         info1.form_name         = argv[2];
1839
1840         info.info1 = &info1;
1841
1842         /* Set the form */
1843
1844         status = rpccli_spoolss_SetForm(cli, mem_ctx,
1845                                         &handle,
1846                                         argv[2],
1847                                         1,
1848                                         info,
1849                                         &werror);
1850
1851  done:
1852         if (is_valid_policy_hnd(&handle))
1853                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1854
1855         return werror;
1856 }
1857
1858 /****************************************************************************
1859 ****************************************************************************/
1860
1861 static const char *get_form_flag(int form_flag)
1862 {
1863         switch (form_flag) {
1864         case SPOOLSS_FORM_USER:
1865                 return "FORM_USER";
1866         case SPOOLSS_FORM_BUILTIN:
1867                 return "FORM_BUILTIN";
1868         case SPOOLSS_FORM_PRINTER:
1869                 return "FORM_PRINTER";
1870         default:
1871                 return "unknown";
1872         }
1873 }
1874
1875 /****************************************************************************
1876 ****************************************************************************/
1877
1878 static void display_form_info1(struct spoolss_FormInfo1 *r)
1879 {
1880         printf("%s\n" \
1881                 "\tflag: %s (%d)\n" \
1882                 "\twidth: %d, length: %d\n" \
1883                 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1884                 r->form_name, get_form_flag(r->flags), r->flags,
1885                 r->size.width, r->size.height,
1886                 r->area.left, r->area.right,
1887                 r->area.top, r->area.bottom);
1888 }
1889
1890 /****************************************************************************
1891 ****************************************************************************/
1892
1893 static void display_form_info2(struct spoolss_FormInfo2 *r)
1894 {
1895         printf("%s\n" \
1896                 "\tflag: %s (%d)\n" \
1897                 "\twidth: %d, length: %d\n" \
1898                 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
1899                 r->form_name, get_form_flag(r->flags), r->flags,
1900                 r->size.width, r->size.height,
1901                 r->area.left, r->area.right,
1902                 r->area.top, r->area.bottom);
1903         printf("\tkeyword: %s\n", r->keyword);
1904         printf("\tstring_type: 0x%08x\n", r->string_type);
1905         printf("\tmui_dll: %s\n", r->mui_dll);
1906         printf("\tressource_id: 0x%08x\n", r->ressource_id);
1907         printf("\tdisplay_name: %s\n", r->display_name);
1908         printf("\tlang_id: %d\n", r->lang_id);
1909         printf("\n");
1910 }
1911
1912 /****************************************************************************
1913 ****************************************************************************/
1914
1915 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1916                                     int argc, const char **argv)
1917 {
1918         POLICY_HND handle;
1919         WERROR werror;
1920         NTSTATUS status;
1921         const char *printername;
1922         DATA_BLOB buffer;
1923         uint32_t offered = 0;
1924         union spoolss_FormInfo info;
1925         uint32_t needed;
1926         uint32_t level = 1;
1927
1928         /* Parse the command arguments */
1929
1930         if (argc < 3 || argc > 5) {
1931                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1932                 return WERR_OK;
1933         }
1934
1935         /* Get a printer handle */
1936
1937         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1938
1939         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1940                                                printername,
1941                                                SEC_FLAG_MAXIMUM_ALLOWED,
1942                                                &handle);
1943         if (!W_ERROR_IS_OK(werror))
1944                 goto done;
1945
1946         if (argc == 4) {
1947                 level = atoi(argv[3]);
1948         }
1949
1950         /* Get the form */
1951
1952         status = rpccli_spoolss_GetForm(cli, mem_ctx,
1953                                         &handle,
1954                                         argv[2],
1955                                         level,
1956                                         NULL,
1957                                         offered,
1958                                         &info,
1959                                         &needed,
1960                                         &werror);
1961         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
1962                 buffer = data_blob_talloc_zero(mem_ctx, needed);
1963                 offered = needed;
1964                 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1965                                                 &handle,
1966                                                 argv[2],
1967                                                 level,
1968                                                 &buffer,
1969                                                 offered,
1970                                                 &info,
1971                                                 &needed,
1972                                                 &werror);
1973         }
1974
1975         if (!NT_STATUS_IS_OK(status)) {
1976                 return werror;
1977         }
1978
1979         switch (level) {
1980         case 1:
1981                 display_form_info1(&info.info1);
1982                 break;
1983         case 2:
1984                 display_form_info2(&info.info2);
1985                 break;
1986         }
1987
1988  done:
1989         if (is_valid_policy_hnd(&handle))
1990                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1991
1992         return werror;
1993 }
1994
1995 /****************************************************************************
1996 ****************************************************************************/
1997
1998 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1999                                        TALLOC_CTX *mem_ctx, int argc,
2000                                        const char **argv)
2001 {
2002         POLICY_HND handle;
2003         WERROR werror;
2004         NTSTATUS status;
2005         const char *printername;
2006
2007         /* Parse the command arguments */
2008
2009         if (argc != 3) {
2010                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2011                 return WERR_OK;
2012         }
2013
2014         /* Get a printer handle */
2015
2016         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2017
2018         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2019                                                printername,
2020                                                SEC_FLAG_MAXIMUM_ALLOWED,
2021                                                &handle);
2022         if (!W_ERROR_IS_OK(werror))
2023                 goto done;
2024
2025         /* Delete the form */
2026
2027         status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2028                                            &handle,
2029                                            argv[2],
2030                                            &werror);
2031         if (!NT_STATUS_IS_OK(status)) {
2032                 return ntstatus_to_werror(status);
2033         }
2034
2035  done:
2036         if (is_valid_policy_hnd(&handle))
2037                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2038
2039         return werror;
2040 }
2041
2042 /****************************************************************************
2043 ****************************************************************************/
2044
2045 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2046                                        TALLOC_CTX *mem_ctx, int argc,
2047                                        const char **argv)
2048 {
2049         POLICY_HND handle;
2050         WERROR werror;
2051         const char *printername;
2052         uint32 num_forms, level = 1, i;
2053         union spoolss_FormInfo *forms;
2054
2055         /* Parse the command arguments */
2056
2057         if (argc < 2 || argc > 4) {
2058                 printf ("Usage: %s <printer> [level]\n", argv[0]);
2059                 return WERR_OK;
2060         }
2061
2062         /* Get a printer handle */
2063
2064         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2065
2066         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2067                                                printername,
2068                                                SEC_FLAG_MAXIMUM_ALLOWED,
2069                                                &handle);
2070         if (!W_ERROR_IS_OK(werror))
2071                 goto done;
2072
2073         if (argc == 3) {
2074                 level = atoi(argv[2]);
2075         }
2076
2077         /* Enumerate forms */
2078
2079         werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2080                                           &handle,
2081                                           level,
2082                                           0,
2083                                           &num_forms,
2084                                           &forms);
2085
2086         if (!W_ERROR_IS_OK(werror))
2087                 goto done;
2088
2089         /* Display output */
2090
2091         for (i = 0; i < num_forms; i++) {
2092                 switch (level) {
2093                 case 1:
2094                         display_form_info1(&forms[i].info1);
2095                         break;
2096                 case 2:
2097                         display_form_info2(&forms[i].info2);
2098                         break;
2099                 }
2100         }
2101
2102  done:
2103         if (is_valid_policy_hnd(&handle))
2104                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2105
2106         return werror;
2107 }
2108
2109 /****************************************************************************
2110 ****************************************************************************/
2111
2112 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2113                                             TALLOC_CTX *mem_ctx,
2114                                             int argc, const char **argv)
2115 {
2116         WERROR result;
2117         NTSTATUS status;
2118         const char *printername;
2119         POLICY_HND pol;
2120         union spoolss_PrinterInfo info;
2121         enum winreg_Type type;
2122         union spoolss_PrinterData data;
2123
2124         /* parse the command arguments */
2125         if (argc < 5) {
2126                 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2127                         " <value> <data>\n",
2128                         argv[0]);
2129                 result = WERR_INVALID_PARAM;
2130                 goto done;
2131         }
2132
2133         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2134
2135         type = REG_NONE;
2136
2137         if (strequal(argv[2], "string")) {
2138                 type = REG_SZ;
2139         }
2140
2141         if (strequal(argv[2], "binary")) {
2142                 type = REG_BINARY;
2143         }
2144
2145         if (strequal(argv[2], "dword")) {
2146                 type = REG_DWORD;
2147         }
2148
2149         if (strequal(argv[2], "multistring")) {
2150                 type = REG_MULTI_SZ;
2151         }
2152
2153         if (type == REG_NONE) {
2154                 printf("Unknown data type: %s\n", argv[2]);
2155                 result =  WERR_INVALID_PARAM;
2156                 goto done;
2157         }
2158
2159         /* get a printer handle */
2160
2161         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2162                                                printername,
2163                                                SEC_FLAG_MAXIMUM_ALLOWED,
2164                                                &pol);
2165         if (!W_ERROR_IS_OK(result)) {
2166                 goto done;
2167         }
2168
2169         result = rpccli_spoolss_getprinter(cli, mem_ctx,
2170                                            &pol,
2171                                            0,
2172                                            0,
2173                                            &info);
2174         if (!W_ERROR_IS_OK(result)) {
2175                 goto done;
2176         }
2177
2178         printf("%s\n", current_timestring(mem_ctx, true));
2179         printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2180
2181         /* Set the printer data */
2182
2183         switch (type) {
2184         case REG_SZ:
2185                 data.string = talloc_strdup(mem_ctx, argv[4]);
2186                 W_ERROR_HAVE_NO_MEMORY(data.string);
2187                 break;
2188         case REG_DWORD:
2189                 data.value = strtoul(argv[4], NULL, 10);
2190                 break;
2191         case REG_BINARY:
2192                 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2193                 break;
2194         case REG_MULTI_SZ: {
2195                 int i, num_strings;
2196                 const char **strings = NULL;
2197
2198                 for (i=4; i<argc; i++) {
2199                         if (strcmp(argv[i], "NULL") == 0) {
2200                                 argv[i] = "";
2201                         }
2202                         if (!add_string_to_array(mem_ctx, argv[i],
2203                                                  &strings,
2204                                                  &num_strings)) {
2205                                 result = WERR_NOMEM;
2206                                 goto done;
2207                         }
2208                 }
2209                 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2210                 if (!data.string_array) {
2211                         result = WERR_NOMEM;
2212                         goto done;
2213                 }
2214                 for (i=0; i < num_strings; i++) {
2215                         data.string_array[i] = strings[i];
2216                 }
2217                 break;
2218                 }
2219         default:
2220                 printf("Unknown data type: %s\n", argv[2]);
2221                 result = WERR_INVALID_PARAM;
2222                 goto done;
2223         }
2224
2225         status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2226                                                &pol,
2227                                                argv[3], /* value_name */
2228                                                type,
2229                                                data,
2230                                                0, /* autocalculated size */
2231                                                &result);
2232         if (!W_ERROR_IS_OK(result)) {
2233                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2234                 goto done;
2235         }
2236         printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2237
2238         result = rpccli_spoolss_getprinter(cli, mem_ctx,
2239                                            &pol,
2240                                            0,
2241                                            0,
2242                                            &info);
2243         if (!W_ERROR_IS_OK(result)) {
2244                 goto done;
2245         }
2246
2247         printf("%s\n", current_timestring(mem_ctx, true));
2248         printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2249
2250 done:
2251         /* cleanup */
2252         if (is_valid_policy_hnd(&pol)) {
2253                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2254         }
2255
2256         return result;
2257 }
2258
2259 /****************************************************************************
2260 ****************************************************************************/
2261
2262 static void display_job_info1(struct spoolss_JobInfo1 *r)
2263 {
2264         printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2265                r->user_name, r->document_name, r->text_status, r->pages_printed,
2266                r->total_pages);
2267 }
2268
2269 /****************************************************************************
2270 ****************************************************************************/
2271
2272 static void display_job_info2(struct spoolss_JobInfo2 *r)
2273 {
2274         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2275                r->position, r->job_id,
2276                r->user_name, r->document_name, r->text_status, r->pages_printed,
2277                r->total_pages, r->size);
2278 }
2279
2280 /****************************************************************************
2281 ****************************************************************************/
2282
2283 static void display_job_info3(struct spoolss_JobInfo3 *r)
2284 {
2285         printf("jobid[%d], next_jobid[%d]\n",
2286                 r->job_id, r->next_job_id);
2287 }
2288
2289 /****************************************************************************
2290 ****************************************************************************/
2291
2292 static void display_job_info4(struct spoolss_JobInfo4 *r)
2293 {
2294         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2295                r->position, r->job_id,
2296                r->user_name, r->document_name, r->text_status, r->pages_printed,
2297                r->total_pages, r->size, r->size_high);
2298 }
2299
2300 /****************************************************************************
2301 ****************************************************************************/
2302
2303 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2304                                       TALLOC_CTX *mem_ctx, int argc,
2305                                       const char **argv)
2306 {
2307         WERROR result;
2308         uint32_t level = 1, count, i;
2309         const char *printername;
2310         POLICY_HND hnd;
2311         union spoolss_JobInfo *info;
2312
2313         if (argc < 2 || argc > 3) {
2314                 printf("Usage: %s printername [level]\n", argv[0]);
2315                 return WERR_OK;
2316         }
2317
2318         if (argc == 3) {
2319                 level = atoi(argv[2]);
2320         }
2321
2322         /* Open printer handle */
2323
2324         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2325
2326         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2327                                                printername,
2328                                                SEC_FLAG_MAXIMUM_ALLOWED,
2329                                                &hnd);
2330         if (!W_ERROR_IS_OK(result))
2331                 goto done;
2332
2333         /* Enumerate ports */
2334
2335         result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2336                                          &hnd,
2337                                          0, /* firstjob */
2338                                          1000, /* numjobs */
2339                                          level,
2340                                          0,
2341                                          &count,
2342                                          &info);
2343         if (!W_ERROR_IS_OK(result)) {
2344                 goto done;
2345         }
2346
2347         for (i = 0; i < count; i++) {
2348                 switch (level) {
2349                 case 1:
2350                         display_job_info1(&info[i].info1);
2351                         break;
2352                 case 2:
2353                         display_job_info2(&info[i].info2);
2354                         break;
2355                 default:
2356                         d_printf("unknown info level %d\n", level);
2357                         break;
2358                 }
2359         }
2360
2361 done:
2362         if (is_valid_policy_hnd(&hnd)) {
2363                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2364         }
2365
2366         return result;
2367 }
2368
2369 /****************************************************************************
2370 ****************************************************************************/
2371
2372 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2373                                   TALLOC_CTX *mem_ctx, int argc,
2374                                   const char **argv)
2375 {
2376         WERROR result;
2377         const char *printername;
2378         struct policy_handle hnd;
2379         uint32_t job_id;
2380         uint32_t level = 1;
2381         union spoolss_JobInfo info;
2382
2383         if (argc < 3 || argc > 4) {
2384                 printf("Usage: %s printername job_id [level]\n", argv[0]);
2385                 return WERR_OK;
2386         }
2387
2388         job_id = atoi(argv[2]);
2389
2390         if (argc == 4) {
2391                 level = atoi(argv[3]);
2392         }
2393
2394         /* Open printer handle */
2395
2396         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2397
2398         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2399                                                printername,
2400                                                SEC_FLAG_MAXIMUM_ALLOWED,
2401                                                &hnd);
2402         if (!W_ERROR_IS_OK(result)) {
2403                 goto done;
2404         }
2405
2406         /* Enumerate ports */
2407
2408         result = rpccli_spoolss_getjob(cli, mem_ctx,
2409                                        &hnd,
2410                                        job_id,
2411                                        level,
2412                                        0,
2413                                        &info);
2414
2415         if (!W_ERROR_IS_OK(result)) {
2416                 goto done;
2417         }
2418
2419         switch (level) {
2420         case 1:
2421                 display_job_info1(&info.info1);
2422                 break;
2423         case 2:
2424                 display_job_info2(&info.info2);
2425                 break;
2426         case 3:
2427                 display_job_info3(&info.info3);
2428                 break;
2429         case 4:
2430                 display_job_info4(&info.info4);
2431                 break;
2432         default:
2433                 d_printf("unknown info level %d\n", level);
2434                 break;
2435         }
2436
2437 done:
2438         if (is_valid_policy_hnd(&hnd)) {
2439                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2440         }
2441
2442         return result;
2443 }
2444
2445
2446 /****************************************************************************
2447 ****************************************************************************/
2448
2449 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2450                                     TALLOC_CTX *mem_ctx, int argc,
2451                                     const char **argv)
2452 {
2453         WERROR result;
2454         NTSTATUS status;
2455         uint32_t i = 0;
2456         const char *printername;
2457         POLICY_HND hnd;
2458         uint32_t value_offered = 0;
2459         const char *value_name = NULL;
2460         uint32_t value_needed;
2461         enum winreg_Type type;
2462         uint8_t *data = NULL;
2463         uint32_t data_offered = 0;
2464         uint32_t data_needed;
2465
2466         if (argc != 2) {
2467                 printf("Usage: %s printername\n", argv[0]);
2468                 return WERR_OK;
2469         }
2470
2471         /* Open printer handle */
2472
2473         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2474
2475         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2476                                                printername,
2477                                                SEC_FLAG_MAXIMUM_ALLOWED,
2478                                                &hnd);
2479         if (!W_ERROR_IS_OK(result)) {
2480                 goto done;
2481         }
2482
2483         /* Enumerate data */
2484
2485         status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2486                                                 &hnd,
2487                                                 i,
2488                                                 value_name,
2489                                                 value_offered,
2490                                                 &value_needed,
2491                                                 &type,
2492                                                 data,
2493                                                 data_offered,
2494                                                 &data_needed,
2495                                                 &result);
2496
2497         data_offered    = data_needed;
2498         value_offered   = value_needed;
2499         data            = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2500         value_name      = talloc_zero_array(mem_ctx, char, value_needed);
2501
2502         while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2503
2504                 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2505                                                         &hnd,
2506                                                         i++,
2507                                                         value_name,
2508                                                         value_offered,
2509                                                         &value_needed,
2510                                                         &type,
2511                                                         data,
2512                                                         data_offered,
2513                                                         &data_needed,
2514                                                         &result);
2515                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2516                         REGISTRY_VALUE v;
2517                         fstrcpy(v.valuename, value_name);
2518                         v.type = type;
2519                         v.size = data_offered;
2520                         v.data_p = data;
2521                         display_reg_value(v);
2522                 }
2523         }
2524
2525         if (W_ERROR_V(result) == ERRnomoreitems) {
2526                 result = W_ERROR(ERRsuccess);
2527         }
2528
2529 done:
2530         if (is_valid_policy_hnd(&hnd)) {
2531                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2532         }
2533
2534         return result;
2535 }
2536
2537 /****************************************************************************
2538 ****************************************************************************/
2539
2540 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2541                                           TALLOC_CTX *mem_ctx, int argc,
2542                                           const char **argv)
2543 {
2544         WERROR result;
2545         uint32 i;
2546         const char *printername;
2547         const char *keyname = NULL;
2548         POLICY_HND hnd;
2549         REGVAL_CTR *ctr = NULL;
2550
2551         if (argc != 3) {
2552                 printf("Usage: %s printername <keyname>\n", argv[0]);
2553                 return WERR_OK;
2554         }
2555
2556         keyname = argv[2];
2557
2558         /* Open printer handle */
2559
2560         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2561
2562         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2563                                                printername,
2564                                                SEC_FLAG_MAXIMUM_ALLOWED,
2565                                                &hnd);
2566         if (!W_ERROR_IS_OK(result))
2567                 goto done;
2568
2569         /* Enumerate subkeys */
2570
2571         if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2572                 return WERR_NOMEM;
2573
2574         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2575
2576         if (!W_ERROR_IS_OK(result))
2577                 goto done;
2578
2579         for (i=0; i < ctr->num_values; i++) {
2580                 display_reg_value(*(ctr->values[i]));
2581         }
2582
2583         TALLOC_FREE( ctr );
2584
2585 done:
2586         if (is_valid_policy_hnd(&hnd))
2587                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2588
2589         return result;
2590 }
2591
2592 /****************************************************************************
2593 ****************************************************************************/
2594
2595 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2596                                              TALLOC_CTX *mem_ctx, int argc,
2597                                              const char **argv)
2598 {
2599         WERROR result;
2600         const char *printername;
2601         const char *keyname = NULL;
2602         POLICY_HND hnd;
2603         uint16 *keylist = NULL, *curkey;
2604
2605         if (argc < 2 || argc > 3) {
2606                 printf("Usage: %s printername [keyname]\n", argv[0]);
2607                 return WERR_OK;
2608         }
2609
2610         if (argc == 3)
2611                 keyname = argv[2];
2612         else
2613                 keyname = "";
2614
2615         /* Open printer handle */
2616
2617         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2618
2619         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2620                                                printername,
2621                                                SEC_FLAG_MAXIMUM_ALLOWED,
2622                                                &hnd);
2623         if (!W_ERROR_IS_OK(result))
2624                 goto done;
2625
2626         /* Enumerate subkeys */
2627
2628         result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2629
2630         if (!W_ERROR_IS_OK(result))
2631                 goto done;
2632
2633         curkey = keylist;
2634         while (*curkey != 0) {
2635                 char *subkey = NULL;
2636                 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2637                             STR_TERMINATE);
2638                 if (!subkey) {
2639                         break;
2640                 }
2641                 printf("%s\n", subkey);
2642                 curkey += strlen(subkey) + 1;
2643         }
2644
2645 done:
2646
2647         SAFE_FREE(keylist);
2648
2649         if (is_valid_policy_hnd(&hnd))
2650                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2651
2652         return result;
2653 }
2654
2655 /****************************************************************************
2656 ****************************************************************************/
2657
2658 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2659                                      TALLOC_CTX *mem_ctx, int argc,
2660                                      const char **argv)
2661 {
2662         const char *printername;
2663         const char *clientname;
2664         POLICY_HND hnd;
2665         WERROR result;
2666         NTSTATUS status;
2667         struct spoolss_NotifyOption option;
2668
2669         if (argc != 2) {
2670                 printf("Usage: %s printername\n", argv[0]);
2671                 result = WERR_OK;
2672                 goto done;
2673         }
2674
2675         /* Open printer */
2676
2677         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2678
2679         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2680                                                printername,
2681                                                SEC_FLAG_MAXIMUM_ALLOWED,
2682                                                &hnd);
2683         if (!W_ERROR_IS_OK(result)) {
2684                 printf("Error opening %s\n", argv[1]);
2685                 goto done;
2686         }
2687
2688         /* Create spool options */
2689
2690         option.version = 2;
2691         option.count = 2;
2692
2693         option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2694         if (option.types == NULL) {
2695                 result = WERR_NOMEM;
2696                 goto done;
2697         }
2698
2699         option.types[0].type = PRINTER_NOTIFY_TYPE;
2700         option.types[0].count = 1;
2701         option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2702         if (option.types[0].fields == NULL) {
2703                 result = WERR_NOMEM;
2704                 goto done;
2705         }
2706         option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2707
2708         option.types[1].type = JOB_NOTIFY_TYPE;
2709         option.types[1].count = 1;
2710         option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2711         if (option.types[1].fields == NULL) {
2712                 result = WERR_NOMEM;
2713                 goto done;
2714         }
2715         option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2716
2717         clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2718         if (!clientname) {
2719                 result = WERR_NOMEM;
2720                 goto done;
2721         }
2722
2723         /* Send rffpcnex */
2724
2725         status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2726                                                                      &hnd,
2727                                                                      0,
2728                                                                      0,
2729                                                                      clientname,
2730                                                                      123,
2731                                                                      &option,
2732                                                                      &result);
2733         if (!W_ERROR_IS_OK(result)) {
2734                 printf("Error rffpcnex %s\n", argv[1]);
2735                 goto done;
2736         }
2737
2738 done:
2739         if (is_valid_policy_hnd(&hnd))
2740                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2741
2742         return result;
2743 }
2744
2745 /****************************************************************************
2746 ****************************************************************************/
2747
2748 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2749                              struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2750 {
2751         union spoolss_PrinterInfo info1, info2;
2752         WERROR werror;
2753         TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2754
2755         printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2756         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2757                                            hnd1,
2758                                            2,
2759                                            0,
2760                                            &info1);
2761         if ( !W_ERROR_IS_OK(werror) ) {
2762                 printf("failed (%s)\n", win_errstr(werror));
2763                 talloc_destroy(mem_ctx);
2764                 return False;
2765         }
2766         printf("ok\n");
2767
2768         printf("Retrieving printer properties for %s...", cli2->desthost);
2769         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2770                                            hnd2,
2771                                            2,
2772                                            0,
2773                                            &info2);
2774         if ( !W_ERROR_IS_OK(werror) ) {
2775                 printf("failed (%s)\n", win_errstr(werror));
2776                 talloc_destroy(mem_ctx);
2777                 return False;
2778         }
2779         printf("ok\n");
2780
2781         talloc_destroy(mem_ctx);
2782
2783         return True;
2784 }
2785
2786 /****************************************************************************
2787 ****************************************************************************/
2788
2789 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2790                                      struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2791 {
2792         union spoolss_PrinterInfo info1, info2;
2793         WERROR werror;
2794         TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2795         SEC_DESC *sd1, *sd2;
2796         bool result = True;
2797
2798
2799         printf("Retrieving printer security for %s...", cli1->desthost);
2800         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2801                                            hnd1,
2802                                            3,
2803                                            0,
2804                                            &info1);
2805         if ( !W_ERROR_IS_OK(werror) ) {
2806                 printf("failed (%s)\n", win_errstr(werror));
2807                 result = False;
2808                 goto done;
2809         }
2810         printf("ok\n");
2811
2812         printf("Retrieving printer security for %s...", cli2->desthost);
2813         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2814                                            hnd2,
2815                                            3,
2816                                            0,
2817                                            &info2);
2818         if ( !W_ERROR_IS_OK(werror) ) {
2819                 printf("failed (%s)\n", win_errstr(werror));
2820                 result = False;
2821                 goto done;
2822         }
2823         printf("ok\n");
2824
2825
2826         printf("++ ");
2827
2828         sd1 = info1.info3.secdesc;
2829         sd2 = info2.info3.secdesc;
2830
2831         if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2832                 printf("NULL secdesc!\n");
2833                 result = False;
2834                 goto done;
2835         }
2836
2837         if (!sec_desc_equal( sd1, sd2 ) ) {
2838                 printf("Security Descriptors *not* equal!\n");
2839                 result = False;
2840                 goto done;
2841         }
2842
2843         printf("Security descriptors match\n");
2844
2845 done:
2846         talloc_destroy(mem_ctx);
2847         return result;
2848 }
2849
2850
2851 /****************************************************************************
2852 ****************************************************************************/
2853
2854 extern struct user_auth_info *rpcclient_auth_info;
2855
2856 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2857                                      TALLOC_CTX *mem_ctx, int argc,
2858                                      const char **argv)
2859 {
2860         const char *printername;
2861         char *printername_path = NULL;
2862         struct cli_state *cli_server2 = NULL;
2863         struct rpc_pipe_client *cli2 = NULL;
2864         POLICY_HND hPrinter1, hPrinter2;
2865         NTSTATUS nt_status;
2866         WERROR werror;
2867
2868         if ( argc != 3 )  {
2869                 printf("Usage: %s <printer> <server>\n", argv[0]);
2870                 return WERR_OK;
2871         }
2872
2873         printername = argv[1];
2874
2875         /* first get the connection to the remote server */
2876
2877         nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2878                                         NULL, 0,
2879                                         "IPC$", "IPC",
2880                                         get_cmdline_auth_info_username(rpcclient_auth_info),
2881                                         lp_workgroup(),
2882                                         get_cmdline_auth_info_password(rpcclient_auth_info),
2883                                         get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2884                                         get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2885
2886         if ( !NT_STATUS_IS_OK(nt_status) )
2887                 return WERR_GENERAL_FAILURE;
2888
2889         nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2890                                              &cli2);
2891         if (!NT_STATUS_IS_OK(nt_status)) {
2892                 printf("failed to open spoolss pipe on server %s (%s)\n",
2893                         argv[2], nt_errstr(nt_status));
2894                 return WERR_GENERAL_FAILURE;
2895         }
2896
2897         /* now open up both printers */
2898
2899         RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2900
2901         printf("Opening %s...", printername_path);
2902
2903         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2904                                                printername_path,
2905                                                PRINTER_ALL_ACCESS,
2906                                                &hPrinter1);
2907         if ( !W_ERROR_IS_OK(werror) ) {
2908                 printf("failed (%s)\n", win_errstr(werror));
2909                 goto done;
2910         }
2911         printf("ok\n");
2912
2913         RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2914
2915         printf("Opening %s...", printername_path);
2916         werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2917                                                printername_path,
2918                                                PRINTER_ALL_ACCESS,
2919                                                &hPrinter2);
2920         if ( !W_ERROR_IS_OK(werror) ) {
2921                  printf("failed (%s)\n", win_errstr(werror));
2922                 goto done;
2923         }
2924         printf("ok\n");
2925
2926         compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2927         compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2928 #if 0
2929         compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2930 #endif
2931
2932
2933 done:
2934         /* cleanup */
2935
2936         printf("Closing printers...");
2937         rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2938         rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2939         printf("ok\n");
2940
2941         /* close the second remote connection */
2942
2943         cli_shutdown( cli_server2 );
2944         return WERR_OK;
2945 }
2946
2947 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
2948 {
2949         printf("print_processor_name: %s\n", r->print_processor_name);
2950 }
2951
2952 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
2953                                      TALLOC_CTX *mem_ctx, int argc,
2954                                      const char **argv)
2955 {
2956         WERROR werror;
2957         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2958         uint32_t num_procs, level = 1, i;
2959         union spoolss_PrintProcessorInfo *procs;
2960
2961         /* Parse the command arguments */
2962
2963         if (argc < 1 || argc > 4) {
2964                 printf ("Usage: %s [environment] [level]\n", argv[0]);
2965                 return WERR_OK;
2966         }
2967
2968         if (argc >= 2) {
2969                 environment = argv[1];
2970         }
2971
2972         if (argc == 3) {
2973                 level = atoi(argv[2]);
2974         }
2975
2976         /* Enumerate Print Processors */
2977
2978         werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
2979                                                     cli->srv_name_slash,
2980                                                     environment,
2981                                                     level,
2982                                                     0,
2983                                                     &num_procs,
2984                                                     &procs);
2985         if (!W_ERROR_IS_OK(werror))
2986                 goto done;
2987
2988         /* Display output */
2989
2990         for (i = 0; i < num_procs; i++) {
2991                 switch (level) {
2992                 case 1:
2993                         display_proc_info1(&procs[i].info1);
2994                         break;
2995                 }
2996         }
2997
2998  done:
2999         return werror;
3000 }
3001
3002 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3003 {
3004         printf("name_array: %s\n", r->name_array);
3005 }
3006
3007 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3008                                                TALLOC_CTX *mem_ctx, int argc,
3009                                                const char **argv)
3010 {
3011         WERROR werror;
3012         const char *print_processor_name = "winprint";
3013         uint32_t num_procs, level = 1, i;
3014         union spoolss_PrintProcDataTypesInfo *procs;
3015
3016         /* Parse the command arguments */
3017
3018         if (argc < 1 || argc > 4) {
3019                 printf ("Usage: %s [environment] [level]\n", argv[0]);
3020                 return WERR_OK;
3021         }
3022
3023         if (argc >= 2) {
3024                 print_processor_name = argv[1];
3025         }
3026
3027         if (argc == 3) {
3028                 level = atoi(argv[2]);
3029         }
3030
3031         /* Enumerate Print Processor Data Types */
3032
3033         werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3034                                                             cli->srv_name_slash,
3035                                                             print_processor_name,
3036                                                             level,
3037                                                             0,
3038                                                             &num_procs,
3039                                                             &procs);
3040         if (!W_ERROR_IS_OK(werror))
3041                 goto done;
3042
3043         /* Display output */
3044
3045         for (i = 0; i < num_procs; i++) {
3046                 switch (level) {
3047                 case 1:
3048                         display_proc_data_types_info1(&procs[i].info1);
3049                         break;
3050                 }
3051         }
3052
3053  done:
3054         return werror;
3055 }
3056
3057 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3058 {
3059         printf("monitor_name: %s\n", r->monitor_name);
3060 }
3061
3062 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3063 {
3064         printf("monitor_name: %s\n", r->monitor_name);
3065         printf("environment: %s\n", r->environment);
3066         printf("dll_name: %s\n", r->dll_name);
3067 }
3068
3069 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3070                                         TALLOC_CTX *mem_ctx, int argc,
3071                                         const char **argv)
3072 {
3073         WERROR werror;
3074         uint32_t count, level = 1, i;
3075         union spoolss_MonitorInfo *info;
3076
3077         /* Parse the command arguments */
3078
3079         if (argc > 2) {
3080                 printf("Usage: %s [level]\n", argv[0]);
3081                 return WERR_OK;
3082         }
3083
3084         if (argc == 2) {
3085                 level = atoi(argv[1]);
3086         }
3087
3088         /* Enumerate Print Monitors */
3089
3090         werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3091                                              cli->srv_name_slash,
3092                                              level,
3093                                              0,
3094                                              &count,
3095                                              &info);
3096         if (!W_ERROR_IS_OK(werror)) {
3097                 goto done;
3098         }
3099
3100         /* Display output */
3101
3102         for (i = 0; i < count; i++) {
3103                 switch (level) {
3104                 case 1:
3105                         display_monitor1(&info[i].info1);
3106                         break;
3107                 case 2:
3108                         display_monitor2(&info[i].info2);
3109                         break;
3110                 }
3111         }
3112
3113  done:
3114         return werror;
3115 }
3116
3117 /* List of commands exported by this module */
3118 struct cmd_set spoolss_commands[] = {
3119
3120         { "SPOOLSS"  },
3121
3122         { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &syntax_spoolss, NULL, "Add a print driver",                  "" },
3123         { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &syntax_spoolss, NULL, "Add a printer",                       "" },
3124         { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &syntax_spoolss, NULL, "Delete a printer driver",             "" },
3125         { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &syntax_spoolss, NULL, "Delete a printer driver with files",  "" },
3126         { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &syntax_spoolss, NULL, "Enumerate printer data",              "" },
3127         { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &syntax_spoolss, NULL, "Enumerate printer data for a key",    "" },
3128         { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &syntax_spoolss, NULL, "Enumerate printer keys",              "" },
3129         { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &syntax_spoolss, NULL, "Enumerate print jobs",                "" },
3130         { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &syntax_spoolss, NULL, "Get print job",                       "" },
3131         { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &syntax_spoolss, NULL, "Enumerate printer ports",             "" },
3132         { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
3133         { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &syntax_spoolss, NULL, "Enumerate printers",                  "" },
3134         { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &syntax_spoolss, NULL, "Get print driver data",               "" },
3135         { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
3136         { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &syntax_spoolss, NULL, "Get print driver information",        "" },
3137         { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &syntax_spoolss, NULL, "Get print driver upload directory",   "" },
3138         { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &syntax_spoolss, NULL, "Get printer info",                    "" },
3139         { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &syntax_spoolss, NULL, "Open printer handle",                 "" },
3140         { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &syntax_spoolss, NULL, "Set printer driver",                  "" },
3141         { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &syntax_spoolss, NULL, "Get print processor directory",       "" },
3142         { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &syntax_spoolss, NULL, "Add form",                            "" },
3143         { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &syntax_spoolss, NULL, "Set form",                            "" },
3144         { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &syntax_spoolss, NULL, "Get form",                            "" },
3145         { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &syntax_spoolss, NULL, "Delete form",                         "" },
3146         { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &syntax_spoolss, NULL, "Enumerate forms",                     "" },
3147         { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &syntax_spoolss, NULL, "Set printer comment",                 "" },
3148         { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &syntax_spoolss, NULL, "Set printername",                 "" },
3149         { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &syntax_spoolss, NULL, "Set REG_SZ printer data",             "" },
3150         { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &syntax_spoolss, NULL, "Rffpcnex test", "" },
3151         { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &syntax_spoolss, NULL, "Printer comparison test", "" },
3152         { "enumprocs",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs,         &syntax_spoolss, NULL, "Enumerate Print Processors",          "" },
3153         { "enumprocdatatypes",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &syntax_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3154         { "enummonitors",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors,      &syntax_spoolss, NULL, "Enumerate Print Monitors", "" },
3155
3156         { NULL }
3157 };