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