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