s3-rpcclient: use is_valid_policy_hnd before closing handles.
[ddiss/samba.git] / source3 / rpcclient / cmd_spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Gerald Carter                2001-2005
6    Copyright (C) Tim Potter                        2000
7    Copyright (C) Andrew Tridgell              1992-1999
8    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpcclient.h"
26
27 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
28 { \
29         _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
30                 _cli->srv_name_slash, _arg); \
31         W_ERROR_HAVE_NO_MEMORY(_printername); \
32 }
33
34 struct table_node {
35         const char      *long_archi;
36         const char      *short_archi;
37         int     version;
38 };
39
40 /* The version int is used by getdrivers.  Note that
41    all architecture strings that support mutliple
42    versions must be grouped together since enumdrivers
43    uses this property to prevent issuing multiple
44    enumdriver calls for the same arch */
45
46
47 static const struct table_node archi_table[]= {
48
49         {"Windows 4.0",          "WIN40",       0 },
50         {"Windows NT x86",       "W32X86",      2 },
51         {"Windows NT x86",       "W32X86",      3 },
52         {"Windows NT R4000",     "W32MIPS",     2 },
53         {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
54         {"Windows NT PowerPC",   "W32PPC",      2 },
55         {"Windows IA64",         "IA64",        3 },
56         {"Windows x64",          "x64",         3 },
57         {NULL,                   "",            -1 }
58 };
59
60 /**
61  * @file
62  *
63  * rpcclient module for SPOOLSS rpc pipe.
64  *
65  * This generally just parses and checks command lines, and then calls
66  * a cli_spoolss function.
67  **/
68
69 /****************************************************************************
70  function to do the mapping between the long architecture name and
71  the short one.
72 ****************************************************************************/
73
74 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
75 {
76         int i=-1;
77
78         DEBUG(107,("Getting architecture dependant directory\n"));
79         do {
80                 i++;
81         } while ( (archi_table[i].long_archi!=NULL ) &&
82                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
83
84         if (archi_table[i].long_archi==NULL) {
85                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
86                 return NULL;
87         }
88
89         /* this might be client code - but shouldn't this be an fstrcpy etc? */
90
91
92         DEBUGADD(108,("index: [%d]\n", i));
93         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
94         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
95
96         return archi_table[i].short_archi;
97 }
98
99 /****************************************************************************
100 ****************************************************************************/
101
102 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
103                                             TALLOC_CTX *mem_ctx,
104                                             int argc, const char **argv)
105 {
106         WERROR          werror;
107         POLICY_HND      hnd;
108
109         if (argc != 2) {
110                 printf("Usage: %s <printername>\n", argv[0]);
111                 return WERR_OK;
112         }
113
114         if (!cli)
115             return WERR_GENERAL_FAILURE;
116
117         /* Open the printer handle */
118
119         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
120                                                argv[1],
121                                                PRINTER_ALL_ACCESS,
122                                                &hnd);
123         if (W_ERROR_IS_OK(werror)) {
124                 printf("Printer %s opened successfully\n", argv[1]);
125                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
126
127                 if (!W_ERROR_IS_OK(werror)) {
128                         printf("Error closing printer handle! (%s)\n",
129                                 get_dos_error_msg(werror));
130                 }
131         }
132
133         return werror;
134 }
135
136
137 /****************************************************************************
138 ****************************************************************************/
139
140 static void display_print_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 WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2426                                       TALLOC_CTX *mem_ctx, int argc,
2427                                       const char **argv)
2428 {
2429         WERROR result;
2430         uint32 level = 1, num_jobs, i;
2431         const char *printername;
2432         POLICY_HND hnd;
2433         JOB_INFO_CTR ctr;
2434
2435         if (argc < 2 || argc > 3) {
2436                 printf("Usage: %s printername [level]\n", argv[0]);
2437                 return WERR_OK;
2438         }
2439
2440         if (argc == 3)
2441                 level = atoi(argv[2]);
2442
2443         /* Open printer handle */
2444
2445         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2446
2447         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2448                                                printername,
2449                                                SEC_FLAG_MAXIMUM_ALLOWED,
2450                                                &hnd);
2451         if (!W_ERROR_IS_OK(result))
2452                 goto done;
2453
2454         /* Enumerate ports */
2455
2456         result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2457                 &num_jobs, &ctr);
2458
2459         if (!W_ERROR_IS_OK(result))
2460                 goto done;
2461
2462         for (i = 0; i < num_jobs; i++) {
2463                 switch(level) {
2464                 case 1:
2465                         display_job_info_1(&ctr.job.job_info_1[i]);
2466                         break;
2467                 case 2:
2468                         display_job_info_2(&ctr.job.job_info_2[i]);
2469                         break;
2470                 default:
2471                         d_printf("unknown info level %d\n", level);
2472                         break;
2473                 }
2474         }
2475
2476 done:
2477         if (is_valid_policy_hnd(&hnd))
2478                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2479
2480         return result;
2481 }
2482
2483 /****************************************************************************
2484 ****************************************************************************/
2485
2486 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2487                                        TALLOC_CTX *mem_ctx, int argc,
2488                                        const char **argv)
2489 {
2490         WERROR result;
2491         uint32 i=0, val_needed, data_needed;
2492         const char *printername;
2493         POLICY_HND hnd;
2494
2495         if (argc != 2) {
2496                 printf("Usage: %s printername\n", argv[0]);
2497                 return WERR_OK;
2498         }
2499
2500         /* Open printer handle */
2501
2502         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2503
2504         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2505                                                printername,
2506                                                SEC_FLAG_MAXIMUM_ALLOWED,
2507                                                &hnd);
2508         if (!W_ERROR_IS_OK(result))
2509                 goto done;
2510
2511         /* Enumerate data */
2512
2513         result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2514                                              &val_needed, &data_needed,
2515                                              NULL);
2516         while (W_ERROR_IS_OK(result)) {
2517                 REGISTRY_VALUE value;
2518                 result = rpccli_spoolss_enumprinterdata(
2519                         cli, mem_ctx, &hnd, i++, val_needed,
2520                         data_needed, 0, 0, &value);
2521                 if (W_ERROR_IS_OK(result))
2522                         display_reg_value(value);
2523         }
2524         if (W_ERROR_V(result) == ERRnomoreitems)
2525                 result = W_ERROR(ERRsuccess);
2526
2527 done:
2528         if (is_valid_policy_hnd(&hnd))
2529                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2530
2531         return result;
2532 }
2533
2534 /****************************************************************************
2535 ****************************************************************************/
2536
2537 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2538                                           TALLOC_CTX *mem_ctx, int argc,
2539                                           const char **argv)
2540 {
2541         WERROR result;
2542         uint32 i;
2543         const char *printername;
2544         const char *keyname = NULL;
2545         POLICY_HND hnd;
2546         REGVAL_CTR *ctr = NULL;
2547
2548         if (argc != 3) {
2549                 printf("Usage: %s printername <keyname>\n", argv[0]);
2550                 return WERR_OK;
2551         }
2552
2553         keyname = argv[2];
2554
2555         /* Open printer handle */
2556
2557         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2558
2559         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2560                                                printername,
2561                                                SEC_FLAG_MAXIMUM_ALLOWED,
2562                                                &hnd);
2563         if (!W_ERROR_IS_OK(result))
2564                 goto done;
2565
2566         /* Enumerate subkeys */
2567
2568         if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2569                 return WERR_NOMEM;
2570
2571         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2572
2573         if (!W_ERROR_IS_OK(result))
2574                 goto done;
2575
2576         for (i=0; i < ctr->num_values; i++) {
2577                 display_reg_value(*(ctr->values[i]));
2578         }
2579
2580         TALLOC_FREE( ctr );
2581
2582 done:
2583         if (is_valid_policy_hnd(&hnd))
2584                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2585
2586         return result;
2587 }
2588
2589 /****************************************************************************
2590 ****************************************************************************/
2591
2592 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2593                                              TALLOC_CTX *mem_ctx, int argc,
2594                                              const char **argv)
2595 {
2596         WERROR result;
2597         const char *printername;
2598         const char *keyname = NULL;
2599         POLICY_HND hnd;
2600         uint16 *keylist = NULL, *curkey;
2601
2602         if (argc < 2 || argc > 3) {
2603                 printf("Usage: %s printername [keyname]\n", argv[0]);
2604                 return WERR_OK;
2605         }
2606
2607         if (argc == 3)
2608                 keyname = argv[2];
2609         else
2610                 keyname = "";
2611
2612         /* Open printer handle */
2613
2614         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2615
2616         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2617                                                printername,
2618                                                SEC_FLAG_MAXIMUM_ALLOWED,
2619                                                &hnd);
2620         if (!W_ERROR_IS_OK(result))
2621                 goto done;
2622
2623         /* Enumerate subkeys */
2624
2625         result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2626
2627         if (!W_ERROR_IS_OK(result))
2628                 goto done;
2629
2630         curkey = keylist;
2631         while (*curkey != 0) {
2632                 char *subkey = NULL;
2633                 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2634                             STR_TERMINATE);
2635                 if (!subkey) {
2636                         break;
2637                 }
2638                 printf("%s\n", subkey);
2639                 curkey += strlen(subkey) + 1;
2640         }
2641
2642 done:
2643
2644         SAFE_FREE(keylist);
2645
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_rffpcnex(struct rpc_pipe_client *cli,
2656                                      TALLOC_CTX *mem_ctx, int argc,
2657                                      const char **argv)
2658 {
2659         const char *printername;
2660         const char *clientname;
2661         POLICY_HND hnd;
2662         WERROR result;
2663         NTSTATUS status;
2664         struct spoolss_NotifyOption option;
2665
2666         if (argc != 2) {
2667                 printf("Usage: %s printername\n", argv[0]);
2668                 result = WERR_OK;
2669                 goto done;
2670         }
2671
2672         /* Open printer */
2673
2674         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2675
2676         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2677                                                printername,
2678                                                SEC_FLAG_MAXIMUM_ALLOWED,
2679                                                &hnd);
2680         if (!W_ERROR_IS_OK(result)) {
2681                 printf("Error opening %s\n", argv[1]);
2682                 goto done;
2683         }
2684
2685         /* Create spool options */
2686
2687         option.version = 2;
2688         option.count = 2;
2689
2690         option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2691         if (option.types == NULL) {
2692                 result = WERR_NOMEM;
2693                 goto done;
2694         }
2695
2696         option.types[0].type = PRINTER_NOTIFY_TYPE;
2697         option.types[0].count = 1;
2698         option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2699         if (option.types[0].fields == NULL) {
2700                 result = WERR_NOMEM;
2701                 goto done;
2702         }
2703         option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2704
2705         option.types[1].type = JOB_NOTIFY_TYPE;
2706         option.types[1].count = 1;
2707         option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2708         if (option.types[1].fields == NULL) {
2709                 result = WERR_NOMEM;
2710                 goto done;
2711         }
2712         option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2713
2714         clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2715         if (!clientname) {
2716                 result = WERR_NOMEM;
2717                 goto done;
2718         }
2719
2720         /* Send rffpcnex */
2721
2722         status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2723                                                                      &hnd,
2724                                                                      0,
2725                                                                      0,
2726                                                                      clientname,
2727                                                                      123,
2728                                                                      &option,
2729                                                                      &result);
2730         if (!W_ERROR_IS_OK(result)) {
2731                 printf("Error rffpcnex %s\n", argv[1]);
2732                 goto done;
2733         }
2734
2735 done:
2736         if (is_valid_policy_hnd(&hnd))
2737                 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2738
2739         return result;
2740 }
2741
2742 /****************************************************************************
2743 ****************************************************************************/
2744
2745 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2746                              struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2747 {
2748         union spoolss_PrinterInfo info1, info2;
2749         WERROR werror;
2750         TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2751
2752         printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2753         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2754                                            hnd1,
2755                                            2,
2756                                            0,
2757                                            &info1);
2758         if ( !W_ERROR_IS_OK(werror) ) {
2759                 printf("failed (%s)\n", win_errstr(werror));
2760                 talloc_destroy(mem_ctx);
2761                 return False;
2762         }
2763         printf("ok\n");
2764
2765         printf("Retrieving printer properties for %s...", cli2->desthost);
2766         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2767                                            hnd2,
2768                                            2,
2769                                            0,
2770                                            &info2);
2771         if ( !W_ERROR_IS_OK(werror) ) {
2772                 printf("failed (%s)\n", win_errstr(werror));
2773                 talloc_destroy(mem_ctx);
2774                 return False;
2775         }
2776         printf("ok\n");
2777
2778         talloc_destroy(mem_ctx);
2779
2780         return True;
2781 }
2782
2783 /****************************************************************************
2784 ****************************************************************************/
2785
2786 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2787                                      struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2788 {
2789         union spoolss_PrinterInfo info1, info2;
2790         WERROR werror;
2791         TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2792         SEC_DESC *sd1, *sd2;
2793         bool result = True;
2794
2795
2796         printf("Retrieving printer security for %s...", cli1->desthost);
2797         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2798                                            hnd1,
2799                                            3,
2800                                            0,
2801                                            &info1);
2802         if ( !W_ERROR_IS_OK(werror) ) {
2803                 printf("failed (%s)\n", win_errstr(werror));
2804                 result = False;
2805                 goto done;
2806         }
2807         printf("ok\n");
2808
2809         printf("Retrieving printer security for %s...", cli2->desthost);
2810         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2811                                            hnd2,
2812                                            3,
2813                                            0,
2814                                            &info2);
2815         if ( !W_ERROR_IS_OK(werror) ) {
2816                 printf("failed (%s)\n", win_errstr(werror));
2817                 result = False;
2818                 goto done;
2819         }
2820         printf("ok\n");
2821
2822
2823         printf("++ ");
2824
2825         sd1 = info1.info3.secdesc;
2826         sd2 = info2.info3.secdesc;
2827
2828         if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2829                 printf("NULL secdesc!\n");
2830                 result = False;
2831                 goto done;
2832         }
2833
2834         if (!sec_desc_equal( sd1, sd2 ) ) {
2835                 printf("Security Descriptors *not* equal!\n");
2836                 result = False;
2837                 goto done;
2838         }
2839
2840         printf("Security descriptors match\n");
2841
2842 done:
2843         talloc_destroy(mem_ctx);
2844         return result;
2845 }
2846
2847
2848 /****************************************************************************
2849 ****************************************************************************/
2850
2851 extern struct user_auth_info *rpcclient_auth_info;
2852
2853 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2854                                      TALLOC_CTX *mem_ctx, int argc,
2855                                      const char **argv)
2856 {
2857         const char *printername;
2858         char *printername_path = NULL;
2859         struct cli_state *cli_server2 = NULL;
2860         struct rpc_pipe_client *cli2 = NULL;
2861         POLICY_HND hPrinter1, hPrinter2;
2862         NTSTATUS nt_status;
2863         WERROR werror;
2864
2865         if ( argc != 3 )  {
2866                 printf("Usage: %s <printer> <server>\n", argv[0]);
2867                 return WERR_OK;
2868         }
2869
2870         printername = argv[1];
2871
2872         /* first get the connection to the remote server */
2873
2874         nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2875                                         NULL, 0,
2876                                         "IPC$", "IPC",
2877                                         get_cmdline_auth_info_username(rpcclient_auth_info),
2878                                         lp_workgroup(),
2879                                         get_cmdline_auth_info_password(rpcclient_auth_info),
2880                                         get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2881                                         get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2882
2883         if ( !NT_STATUS_IS_OK(nt_status) )
2884                 return WERR_GENERAL_FAILURE;
2885
2886         nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2887                                              &cli2);
2888         if (!NT_STATUS_IS_OK(nt_status)) {
2889                 printf("failed to open spoolss pipe on server %s (%s)\n",
2890                         argv[2], nt_errstr(nt_status));
2891                 return WERR_GENERAL_FAILURE;
2892         }
2893
2894         /* now open up both printers */
2895
2896         RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2897
2898         printf("Opening %s...", printername_path);
2899
2900         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2901                                                printername_path,
2902                                                PRINTER_ALL_ACCESS,
2903                                                &hPrinter1);
2904         if ( !W_ERROR_IS_OK(werror) ) {
2905                 printf("failed (%s)\n", win_errstr(werror));
2906                 goto done;
2907         }
2908         printf("ok\n");
2909
2910         RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2911
2912         printf("Opening %s...", printername_path);
2913         werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2914                                                printername_path,
2915                                                PRINTER_ALL_ACCESS,
2916                                                &hPrinter2);
2917         if ( !W_ERROR_IS_OK(werror) ) {
2918                  printf("failed (%s)\n", win_errstr(werror));
2919                 goto done;
2920         }
2921         printf("ok\n");
2922
2923         compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2924         compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2925 #if 0
2926         compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2927 #endif
2928
2929
2930 done:
2931         /* cleanup */
2932
2933         printf("Closing printers...");
2934         rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2935         rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2936         printf("ok\n");
2937
2938         /* close the second remote connection */
2939
2940         cli_shutdown( cli_server2 );
2941         return WERR_OK;
2942 }
2943
2944 /* List of commands exported by this module */
2945 struct cmd_set spoolss_commands[] = {
2946
2947         { "SPOOLSS"  },
2948
2949         { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &syntax_spoolss, NULL, "Add a print driver",                  "" },
2950         { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &syntax_spoolss, NULL, "Add a printer",                       "" },
2951         { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &syntax_spoolss, NULL, "Delete a printer driver",             "" },
2952         { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &syntax_spoolss, NULL, "Delete a printer driver with files",  "" },
2953         { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &syntax_spoolss, NULL, "Enumerate printer data",              "" },
2954         { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &syntax_spoolss, NULL, "Enumerate printer data for a key",    "" },
2955         { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &syntax_spoolss, NULL, "Enumerate printer keys",              "" },
2956         { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &syntax_spoolss, NULL, "Enumerate print jobs",                "" },
2957         { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &syntax_spoolss, NULL, "Enumerate printer ports",             "" },
2958         { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
2959         { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &syntax_spoolss, NULL, "Enumerate printers",                  "" },
2960         { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &syntax_spoolss, NULL, "Get print driver data",               "" },
2961         { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
2962         { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &syntax_spoolss, NULL, "Get print driver information",        "" },
2963         { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &syntax_spoolss, NULL, "Get print driver upload directory",   "" },
2964         { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &syntax_spoolss, NULL, "Get printer info",                    "" },
2965         { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &syntax_spoolss, NULL, "Open printer handle",                 "" },
2966         { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &syntax_spoolss, NULL, "Set printer driver",                  "" },
2967         { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &syntax_spoolss, NULL, "Get print processor directory",       "" },
2968         { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &syntax_spoolss, NULL, "Add form",                            "" },
2969         { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &syntax_spoolss, NULL, "Set form",                            "" },
2970         { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &syntax_spoolss, NULL, "Get form",                            "" },
2971         { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &syntax_spoolss, NULL, "Delete form",                         "" },
2972         { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &syntax_spoolss, NULL, "Enumerate forms",                     "" },
2973         { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &syntax_spoolss, NULL, "Set printer comment",                 "" },
2974         { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &syntax_spoolss, NULL, "Set printername",                 "" },
2975         { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &syntax_spoolss, NULL, "Set REG_SZ printer data",             "" },
2976         { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &syntax_spoolss, NULL, "Rffpcnex test", "" },
2977         { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &syntax_spoolss, NULL, "Printer comparison test", "" },
2978
2979         { NULL }
2980 };