Merge branch 'master' of ssh://git.samba.org/data/git/samba into abartlet-devel
[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 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2456                                   TALLOC_CTX *mem_ctx, int argc,
2457                                   const char **argv)
2458 {
2459         WERROR result;
2460         NTSTATUS status;
2461         const char *printername;
2462         struct policy_handle hnd;
2463         uint32_t job_id;
2464         enum spoolss_JobControl command;
2465
2466         if (argc != 4) {
2467                 printf("Usage: %s printername job_id command\n", argv[0]);
2468                 return WERR_OK;
2469         }
2470
2471         job_id = atoi(argv[2]);
2472         command = atoi(argv[3]);
2473
2474         /* Open printer handle */
2475
2476         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2477
2478         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2479                                                printername,
2480                                                SEC_FLAG_MAXIMUM_ALLOWED,
2481                                                &hnd);
2482         if (!W_ERROR_IS_OK(result)) {
2483                 goto done;
2484         }
2485
2486         /* Set Job */
2487
2488         status = rpccli_spoolss_SetJob(cli, mem_ctx,
2489                                        &hnd,
2490                                        job_id,
2491                                        NULL,
2492                                        command,
2493                                        &result);
2494
2495         if (!W_ERROR_IS_OK(result)) {
2496                 goto done;
2497         }
2498
2499 done:
2500         if (is_valid_policy_hnd(&hnd)) {
2501                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2502         }
2503
2504         return result;
2505 }
2506
2507 /****************************************************************************
2508 ****************************************************************************/
2509
2510 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2511                                     TALLOC_CTX *mem_ctx, int argc,
2512                                     const char **argv)
2513 {
2514         WERROR result;
2515         NTSTATUS status;
2516         uint32_t i = 0;
2517         const char *printername;
2518         struct policy_handle hnd;
2519         uint32_t value_offered = 0;
2520         const char *value_name = NULL;
2521         uint32_t value_needed;
2522         enum winreg_Type type;
2523         uint8_t *data = NULL;
2524         uint32_t data_offered = 0;
2525         uint32_t data_needed;
2526
2527         if (argc != 2) {
2528                 printf("Usage: %s printername\n", argv[0]);
2529                 return WERR_OK;
2530         }
2531
2532         /* Open printer handle */
2533
2534         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2535
2536         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2537                                                printername,
2538                                                SEC_FLAG_MAXIMUM_ALLOWED,
2539                                                &hnd);
2540         if (!W_ERROR_IS_OK(result)) {
2541                 goto done;
2542         }
2543
2544         /* Enumerate data */
2545
2546         status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2547                                                 &hnd,
2548                                                 i,
2549                                                 value_name,
2550                                                 value_offered,
2551                                                 &value_needed,
2552                                                 &type,
2553                                                 data,
2554                                                 data_offered,
2555                                                 &data_needed,
2556                                                 &result);
2557
2558         data_offered    = data_needed;
2559         value_offered   = value_needed;
2560         data            = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2561         value_name      = talloc_zero_array(mem_ctx, char, value_needed);
2562
2563         while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2564
2565                 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2566                                                         &hnd,
2567                                                         i++,
2568                                                         value_name,
2569                                                         value_offered,
2570                                                         &value_needed,
2571                                                         &type,
2572                                                         data,
2573                                                         data_offered,
2574                                                         &data_needed,
2575                                                         &result);
2576                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2577                         REGISTRY_VALUE v;
2578                         fstrcpy(v.valuename, value_name);
2579                         v.type = type;
2580                         v.size = data_offered;
2581                         v.data_p = data;
2582                         display_reg_value(v);
2583                 }
2584         }
2585
2586         if (W_ERROR_V(result) == ERRnomoreitems) {
2587                 result = W_ERROR(ERRsuccess);
2588         }
2589
2590 done:
2591         if (is_valid_policy_hnd(&hnd)) {
2592                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2593         }
2594
2595         return result;
2596 }
2597
2598 /****************************************************************************
2599 ****************************************************************************/
2600
2601 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2602                                           TALLOC_CTX *mem_ctx, int argc,
2603                                           const char **argv)
2604 {
2605         WERROR result;
2606         uint32_t i;
2607         const char *printername;
2608         struct policy_handle hnd;
2609         uint32_t count;
2610         struct spoolss_PrinterEnumValues *info;
2611
2612         if (argc != 3) {
2613                 printf("Usage: %s printername <keyname>\n", argv[0]);
2614                 return WERR_OK;
2615         }
2616
2617         /* Open printer handle */
2618
2619         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2620
2621         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2622                                                printername,
2623                                                SEC_FLAG_MAXIMUM_ALLOWED,
2624                                                &hnd);
2625         if (!W_ERROR_IS_OK(result)) {
2626                 goto done;
2627         }
2628
2629         /* Enumerate subkeys */
2630
2631         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2632                                                   &hnd,
2633                                                   argv[2],
2634                                                   0,
2635                                                   &count,
2636                                                   &info);
2637         if (!W_ERROR_IS_OK(result)) {
2638                 goto done;
2639         }
2640
2641         for (i=0; i < count; i++) {
2642                 display_printer_data(info[i].value_name,
2643                                      info[i].type,
2644                                      info[i].data);
2645         }
2646
2647  done:
2648         if (is_valid_policy_hnd(&hnd)) {
2649                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2650         }
2651
2652         return result;
2653 }
2654
2655 /****************************************************************************
2656 ****************************************************************************/
2657
2658 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2659                                           TALLOC_CTX *mem_ctx, int argc,
2660                                           const char **argv)
2661 {
2662         WERROR result;
2663         const char *printername;
2664         const char *keyname = NULL;
2665         struct policy_handle hnd;
2666         const char **key_buffer = NULL;
2667         int i;
2668
2669         if (argc < 2 || argc > 3) {
2670                 printf("Usage: %s printername [keyname]\n", argv[0]);
2671                 return WERR_OK;
2672         }
2673
2674         if (argc == 3) {
2675                 keyname = argv[2];
2676         } else {
2677                 keyname = "";
2678         }
2679
2680         /* Open printer handle */
2681
2682         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2683
2684         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2685                                                printername,
2686                                                SEC_FLAG_MAXIMUM_ALLOWED,
2687                                                &hnd);
2688         if (!W_ERROR_IS_OK(result)) {
2689                 goto done;
2690         }
2691
2692         /* Enumerate subkeys */
2693
2694         result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2695                                                &hnd,
2696                                                keyname,
2697                                                &key_buffer,
2698                                                0);
2699
2700         if (!W_ERROR_IS_OK(result)) {
2701                 goto done;
2702         }
2703
2704         for (i=0; key_buffer && key_buffer[i]; i++) {
2705                 printf("%s\n", key_buffer[i]);
2706         }
2707
2708  done:
2709
2710         if (is_valid_policy_hnd(&hnd)) {
2711                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2712         }
2713
2714         return result;
2715 }
2716
2717 /****************************************************************************
2718 ****************************************************************************/
2719
2720 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2721                                      TALLOC_CTX *mem_ctx, int argc,
2722                                      const char **argv)
2723 {
2724         const char *printername;
2725         const char *clientname;
2726         struct policy_handle hnd;
2727         WERROR result;
2728         NTSTATUS status;
2729         struct spoolss_NotifyOption option;
2730
2731         if (argc != 2) {
2732                 printf("Usage: %s printername\n", argv[0]);
2733                 result = WERR_OK;
2734                 goto done;
2735         }
2736
2737         /* Open printer */
2738
2739         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2740
2741         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2742                                                printername,
2743                                                SEC_FLAG_MAXIMUM_ALLOWED,
2744                                                &hnd);
2745         if (!W_ERROR_IS_OK(result)) {
2746                 printf("Error opening %s\n", argv[1]);
2747                 goto done;
2748         }
2749
2750         /* Create spool options */
2751
2752         option.version = 2;
2753         option.count = 2;
2754
2755         option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2756         if (option.types == NULL) {
2757                 result = WERR_NOMEM;
2758                 goto done;
2759         }
2760
2761         option.types[0].type = PRINTER_NOTIFY_TYPE;
2762         option.types[0].count = 1;
2763         option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
2764         if (option.types[0].fields == NULL) {
2765                 result = WERR_NOMEM;
2766                 goto done;
2767         }
2768         option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
2769
2770         option.types[1].type = JOB_NOTIFY_TYPE;
2771         option.types[1].count = 1;
2772         option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
2773         if (option.types[1].fields == NULL) {
2774                 result = WERR_NOMEM;
2775                 goto done;
2776         }
2777         option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
2778
2779         clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2780         if (!clientname) {
2781                 result = WERR_NOMEM;
2782                 goto done;
2783         }
2784
2785         /* Send rffpcnex */
2786
2787         status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2788                                                                      &hnd,
2789                                                                      0,
2790                                                                      0,
2791                                                                      clientname,
2792                                                                      123,
2793                                                                      &option,
2794                                                                      &result);
2795         if (!W_ERROR_IS_OK(result)) {
2796                 printf("Error rffpcnex %s\n", argv[1]);
2797                 goto done;
2798         }
2799
2800 done:
2801         if (is_valid_policy_hnd(&hnd))
2802                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2803
2804         return result;
2805 }
2806
2807 /****************************************************************************
2808 ****************************************************************************/
2809
2810 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
2811                              struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
2812 {
2813         union spoolss_PrinterInfo info1, info2;
2814         WERROR werror;
2815         TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2816
2817         printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2818         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2819                                            hnd1,
2820                                            2,
2821                                            0,
2822                                            &info1);
2823         if ( !W_ERROR_IS_OK(werror) ) {
2824                 printf("failed (%s)\n", win_errstr(werror));
2825                 talloc_destroy(mem_ctx);
2826                 return false;
2827         }
2828         printf("ok\n");
2829
2830         printf("Retrieving printer properties for %s...", cli2->desthost);
2831         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2832                                            hnd2,
2833                                            2,
2834                                            0,
2835                                            &info2);
2836         if ( !W_ERROR_IS_OK(werror) ) {
2837                 printf("failed (%s)\n", win_errstr(werror));
2838                 talloc_destroy(mem_ctx);
2839                 return false;
2840         }
2841         printf("ok\n");
2842
2843         talloc_destroy(mem_ctx);
2844
2845         return true;
2846 }
2847
2848 /****************************************************************************
2849 ****************************************************************************/
2850
2851 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
2852                                      struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
2853 {
2854         union spoolss_PrinterInfo info1, info2;
2855         WERROR werror;
2856         TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2857         SEC_DESC *sd1, *sd2;
2858         bool result = true;
2859
2860
2861         printf("Retrieving printer security for %s...", cli1->desthost);
2862         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2863                                            hnd1,
2864                                            3,
2865                                            0,
2866                                            &info1);
2867         if ( !W_ERROR_IS_OK(werror) ) {
2868                 printf("failed (%s)\n", win_errstr(werror));
2869                 result = false;
2870                 goto done;
2871         }
2872         printf("ok\n");
2873
2874         printf("Retrieving printer security for %s...", cli2->desthost);
2875         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2876                                            hnd2,
2877                                            3,
2878                                            0,
2879                                            &info2);
2880         if ( !W_ERROR_IS_OK(werror) ) {
2881                 printf("failed (%s)\n", win_errstr(werror));
2882                 result = false;
2883                 goto done;
2884         }
2885         printf("ok\n");
2886
2887
2888         printf("++ ");
2889
2890         sd1 = info1.info3.secdesc;
2891         sd2 = info2.info3.secdesc;
2892
2893         if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2894                 printf("NULL secdesc!\n");
2895                 result = false;
2896                 goto done;
2897         }
2898
2899         if (!security_descriptor_equal( sd1, sd2 ) ) {
2900                 printf("Security Descriptors *not* equal!\n");
2901                 result = false;
2902                 goto done;
2903         }
2904
2905         printf("Security descriptors match\n");
2906
2907 done:
2908         talloc_destroy(mem_ctx);
2909         return result;
2910 }
2911
2912
2913 /****************************************************************************
2914 ****************************************************************************/
2915
2916 extern struct user_auth_info *rpcclient_auth_info;
2917
2918 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2919                                      TALLOC_CTX *mem_ctx, int argc,
2920                                      const char **argv)
2921 {
2922         const char *printername;
2923         char *printername_path = NULL;
2924         struct cli_state *cli_server2 = NULL;
2925         struct rpc_pipe_client *cli2 = NULL;
2926         struct policy_handle hPrinter1, hPrinter2;
2927         NTSTATUS nt_status;
2928         WERROR werror;
2929
2930         if ( argc != 3 )  {
2931                 printf("Usage: %s <printer> <server>\n", argv[0]);
2932                 return WERR_OK;
2933         }
2934
2935         printername = argv[1];
2936
2937         /* first get the connection to the remote server */
2938
2939         nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2940                                         NULL, 0,
2941                                         "IPC$", "IPC",
2942                                         get_cmdline_auth_info_username(rpcclient_auth_info),
2943                                         lp_workgroup(),
2944                                         get_cmdline_auth_info_password(rpcclient_auth_info),
2945                                         get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2946                                         get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2947
2948         if ( !NT_STATUS_IS_OK(nt_status) )
2949                 return WERR_GENERAL_FAILURE;
2950
2951         nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
2952                                              &cli2);
2953         if (!NT_STATUS_IS_OK(nt_status)) {
2954                 printf("failed to open spoolss pipe on server %s (%s)\n",
2955                         argv[2], nt_errstr(nt_status));
2956                 return WERR_GENERAL_FAILURE;
2957         }
2958
2959         /* now open up both printers */
2960
2961         RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2962
2963         printf("Opening %s...", printername_path);
2964
2965         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2966                                                printername_path,
2967                                                PRINTER_ALL_ACCESS,
2968                                                &hPrinter1);
2969         if ( !W_ERROR_IS_OK(werror) ) {
2970                 printf("failed (%s)\n", win_errstr(werror));
2971                 goto done;
2972         }
2973         printf("ok\n");
2974
2975         RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2976
2977         printf("Opening %s...", printername_path);
2978         werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2979                                                printername_path,
2980                                                PRINTER_ALL_ACCESS,
2981                                                &hPrinter2);
2982         if ( !W_ERROR_IS_OK(werror) ) {
2983                  printf("failed (%s)\n", win_errstr(werror));
2984                 goto done;
2985         }
2986         printf("ok\n");
2987
2988         compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2989         compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2990 #if 0
2991         compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2992 #endif
2993
2994
2995 done:
2996         /* cleanup */
2997
2998         printf("Closing printers...");
2999         rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3000         rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3001         printf("ok\n");
3002
3003         /* close the second remote connection */
3004
3005         cli_shutdown( cli_server2 );
3006         return WERR_OK;
3007 }
3008
3009 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3010 {
3011         printf("print_processor_name: %s\n", r->print_processor_name);
3012 }
3013
3014 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3015                                      TALLOC_CTX *mem_ctx, int argc,
3016                                      const char **argv)
3017 {
3018         WERROR werror;
3019         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3020         uint32_t num_procs, level = 1, i;
3021         union spoolss_PrintProcessorInfo *procs;
3022
3023         /* Parse the command arguments */
3024
3025         if (argc < 1 || argc > 4) {
3026                 printf ("Usage: %s [environment] [level]\n", argv[0]);
3027                 return WERR_OK;
3028         }
3029
3030         if (argc >= 2) {
3031                 environment = argv[1];
3032         }
3033
3034         if (argc == 3) {
3035                 level = atoi(argv[2]);
3036         }
3037
3038         /* Enumerate Print Processors */
3039
3040         werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3041                                                     cli->srv_name_slash,
3042                                                     environment,
3043                                                     level,
3044                                                     0,
3045                                                     &num_procs,
3046                                                     &procs);
3047         if (!W_ERROR_IS_OK(werror))
3048                 goto done;
3049
3050         /* Display output */
3051
3052         for (i = 0; i < num_procs; i++) {
3053                 switch (level) {
3054                 case 1:
3055                         display_proc_info1(&procs[i].info1);
3056                         break;
3057                 }
3058         }
3059
3060  done:
3061         return werror;
3062 }
3063
3064 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3065 {
3066         printf("name_array: %s\n", r->name_array);
3067 }
3068
3069 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3070                                                TALLOC_CTX *mem_ctx, int argc,
3071                                                const char **argv)
3072 {
3073         WERROR werror;
3074         const char *print_processor_name = "winprint";
3075         uint32_t num_procs, level = 1, i;
3076         union spoolss_PrintProcDataTypesInfo *procs;
3077
3078         /* Parse the command arguments */
3079
3080         if (argc < 1 || argc > 4) {
3081                 printf ("Usage: %s [environment] [level]\n", argv[0]);
3082                 return WERR_OK;
3083         }
3084
3085         if (argc >= 2) {
3086                 print_processor_name = argv[1];
3087         }
3088
3089         if (argc == 3) {
3090                 level = atoi(argv[2]);
3091         }
3092
3093         /* Enumerate Print Processor Data Types */
3094
3095         werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3096                                                             cli->srv_name_slash,
3097                                                             print_processor_name,
3098                                                             level,
3099                                                             0,
3100                                                             &num_procs,
3101                                                             &procs);
3102         if (!W_ERROR_IS_OK(werror))
3103                 goto done;
3104
3105         /* Display output */
3106
3107         for (i = 0; i < num_procs; i++) {
3108                 switch (level) {
3109                 case 1:
3110                         display_proc_data_types_info1(&procs[i].info1);
3111                         break;
3112                 }
3113         }
3114
3115  done:
3116         return werror;
3117 }
3118
3119 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3120 {
3121         printf("monitor_name: %s\n", r->monitor_name);
3122 }
3123
3124 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3125 {
3126         printf("monitor_name: %s\n", r->monitor_name);
3127         printf("environment: %s\n", r->environment);
3128         printf("dll_name: %s\n", r->dll_name);
3129 }
3130
3131 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3132                                         TALLOC_CTX *mem_ctx, int argc,
3133                                         const char **argv)
3134 {
3135         WERROR werror;
3136         uint32_t count, level = 1, i;
3137         union spoolss_MonitorInfo *info;
3138
3139         /* Parse the command arguments */
3140
3141         if (argc > 2) {
3142                 printf("Usage: %s [level]\n", argv[0]);
3143                 return WERR_OK;
3144         }
3145
3146         if (argc == 2) {
3147                 level = atoi(argv[1]);
3148         }
3149
3150         /* Enumerate Print Monitors */
3151
3152         werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3153                                              cli->srv_name_slash,
3154                                              level,
3155                                              0,
3156                                              &count,
3157                                              &info);
3158         if (!W_ERROR_IS_OK(werror)) {
3159                 goto done;
3160         }
3161
3162         /* Display output */
3163
3164         for (i = 0; i < count; i++) {
3165                 switch (level) {
3166                 case 1:
3167                         display_monitor1(&info[i].info1);
3168                         break;
3169                 case 2:
3170                         display_monitor2(&info[i].info2);
3171                         break;
3172                 }
3173         }
3174
3175  done:
3176         return werror;
3177 }
3178
3179 /* List of commands exported by this module */
3180 struct cmd_set spoolss_commands[] = {
3181
3182         { "SPOOLSS"  },
3183
3184         { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &ndr_table_spoolss.syntax_id, NULL, "Add a print driver",                  "" },
3185         { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &ndr_table_spoolss.syntax_id, NULL, "Add a printer",                       "" },
3186         { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver",             "" },
3187         { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files",  "" },
3188         { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data",              "" },
3189         { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key",    "" },
3190         { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys",              "" },
3191         { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs",                "" },
3192         { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &ndr_table_spoolss.syntax_id, NULL, "Get print job",                       "" },
3193         { "setjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job,            &ndr_table_spoolss.syntax_id, NULL, "Set print job",                       "" },
3194         { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports",             "" },
3195         { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3196         { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers",                  "" },
3197         { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &ndr_table_spoolss.syntax_id, NULL, "Get print driver data",               "" },
3198         { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3199         { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &ndr_table_spoolss.syntax_id, NULL, "Get print driver information",        "" },
3200         { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory",   "" },
3201         { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &ndr_table_spoolss.syntax_id, NULL, "Get printer info",                    "" },
3202         { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &ndr_table_spoolss.syntax_id, NULL, "Open printer handle",                 "" },
3203         { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &ndr_table_spoolss.syntax_id, NULL, "Set printer driver",                  "" },
3204         { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory",       "" },
3205         { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &ndr_table_spoolss.syntax_id, NULL, "Add form",                            "" },
3206         { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &ndr_table_spoolss.syntax_id, NULL, "Set form",                            "" },
3207         { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &ndr_table_spoolss.syntax_id, NULL, "Get form",                            "" },
3208         { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &ndr_table_spoolss.syntax_id, NULL, "Delete form",                         "" },
3209         { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms",                     "" },
3210         { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &ndr_table_spoolss.syntax_id, NULL, "Set printer comment",                 "" },
3211         { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &ndr_table_spoolss.syntax_id, NULL, "Set printername",                 "" },
3212         { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data",             "" },
3213         { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3214         { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3215         { "enumprocs",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors",          "" },
3216         { "enumprocdatatypes",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3217         { "enummonitors",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors,      &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3218
3219         { NULL }
3220 };