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