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