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