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