r2009: compile-fix for #1626 (spotted by Olaf Flebbe
[kai/samba-autobuild/.git] / source3 / rpcclient / cmd_spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Gerald Carter                     2001
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 2 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, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "rpcclient.h"
27
28 struct table_node {
29         const char      *long_archi;
30         const char      *short_archi;
31         int     version;
32 };
33  
34 static const struct table_node archi_table[]= {
35
36         {"Windows 4.0",          "WIN40",       0 },
37         {"Windows NT x86",       "W32X86",      2 },
38         {"Windows NT x86",       "W32X86",      3 },
39         {"Windows NT R4000",     "W32MIPS",     2 },
40         {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
41         {"Windows NT PowerPC",   "W32PPC",      2 },
42         {"Windows IA64",         "IA64",        3 },
43         {NULL,                   "",            -1 }
44 };
45
46 /**
47  * @file
48  *
49  * rpcclient module for SPOOLSS rpc pipe.
50  *
51  * This generally just parses and checks command lines, and then calls
52  * a cli_spoolss function.
53  **/
54
55 /****************************************************************************
56 function to do the mapping between the long architecture name and
57 the short one.
58 ****************************************************************************/
59 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
60 {
61         int i=-1;
62
63         DEBUG(107,("Getting architecture dependant directory\n"));
64         do {
65                 i++;
66         } while ( (archi_table[i].long_archi!=NULL ) &&
67                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
68
69         if (archi_table[i].long_archi==NULL) {
70                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
71                 return NULL;
72         }
73
74         /* this might be client code - but shouldn't this be an fstrcpy etc? */
75
76
77         DEBUGADD(108,("index: [%d]\n", i));
78         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
79         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
80
81         return archi_table[i].short_archi;
82 }
83
84 #if 0
85 /**********************************************************************
86  * dummy function  -- placeholder
87   */
88 static WERROR cmd_spoolss_not_implemented(struct cli_state *cli, 
89                                             TALLOC_CTX *mem_ctx,
90                                             int argc, const char **argv)
91 {
92         printf ("(*) This command is not currently implemented.\n");
93         return WERR_OK;
94 }
95 #endif
96
97 /***********************************************************************
98  * Get printer information
99  */
100 static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli, 
101                                             TALLOC_CTX *mem_ctx,
102                                             int argc, const char **argv)
103 {
104         WERROR          werror;
105         fstring         printername;
106         fstring         servername, user;
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         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
118         strupper_m(servername);
119         fstrcpy(user, cli->user_name);
120         fstrcpy(printername, argv[1]);
121
122         /* Open the printer handle */
123
124         werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
125                                              "", PRINTER_ALL_ACCESS, 
126                                              servername, user, &hnd);
127
128         if (W_ERROR_IS_OK(werror)) {
129                 printf("Printer %s opened successfully\n", printername);
130                 werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
131
132                 if (!W_ERROR_IS_OK(werror)) {
133                         printf("Error closing printer handle! (%s)\n", 
134                                 get_dos_error_msg(werror));
135                 }
136         }
137
138         return werror;
139 }
140
141
142 /****************************************************************************
143 printer info level 0 display function
144 ****************************************************************************/
145 static void display_print_info_0(PRINTER_INFO_0 *i0)
146 {
147         fstring name = "";
148         fstring servername = "";
149
150         if (!i0)
151                 return;
152
153         rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
154
155         rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
156   
157         printf("\tprintername:[%s]\n", name);
158         printf("\tservername:[%s]\n", servername);
159         printf("\tcjobs:[0x%x]\n", i0->cjobs);
160         printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
161         
162         printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month, 
163                i0->day, i0->dayofweek);
164         printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute, 
165                i0->second, i0->milliseconds);
166         
167         printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
168         printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
169         
170         printf("\tmajorversion:[0x%x]\n", i0->major_version);
171         printf("\tbuildversion:[0x%x]\n", i0->build_version);
172         
173         printf("\tunknown7:[0x%x]\n", i0->unknown7);
174         printf("\tunknown8:[0x%x]\n", i0->unknown8);
175         printf("\tunknown9:[0x%x]\n", i0->unknown9);
176         printf("\tsession_counter:[0x%x]\n", i0->session_counter);
177         printf("\tunknown11:[0x%x]\n", i0->unknown11);
178         printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
179         printf("\tunknown13:[0x%x]\n", i0->unknown13);
180         printf("\tunknown14:[0x%x]\n", i0->unknown14);
181         printf("\tunknown15:[0x%x]\n", i0->unknown15);
182         printf("\tunknown16:[0x%x]\n", i0->unknown16);
183         printf("\tchange_id:[0x%x]\n", i0->change_id);
184         printf("\tunknown18:[0x%x]\n", i0->unknown18);
185         printf("\tstatus:[0x%x]\n", i0->status);
186         printf("\tunknown20:[0x%x]\n", i0->unknown20);
187         printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
188         printf("\tunknown22:[0x%x]\n", i0->unknown22);
189         printf("\tunknown23:[0x%x]\n", i0->unknown23);
190         printf("\tunknown24:[0x%x]\n", i0->unknown24);
191         printf("\tunknown25:[0x%x]\n", i0->unknown25);
192         printf("\tunknown26:[0x%x]\n", i0->unknown26);
193         printf("\tunknown27:[0x%x]\n", i0->unknown27);
194         printf("\tunknown28:[0x%x]\n", i0->unknown28);
195         printf("\tunknown29:[0x%x]\n", i0->unknown29);
196
197         printf("\n");
198 }
199
200 /****************************************************************************
201 printer info level 1 display function
202 ****************************************************************************/
203 static void display_print_info_1(PRINTER_INFO_1 *i1)
204 {
205         fstring desc = "";
206         fstring name = "";
207         fstring comm = "";
208
209         rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
210                     STR_TERMINATE);
211
212         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
213         rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
214
215         printf("\tflags:[0x%x]\n", i1->flags);
216         printf("\tname:[%s]\n", name);
217         printf("\tdescription:[%s]\n", desc);
218         printf("\tcomment:[%s]\n", comm);
219
220         printf("\n");
221 }
222
223 /****************************************************************************
224 printer info level 2 display function
225 ****************************************************************************/
226 static void display_print_info_2(PRINTER_INFO_2 *i2)
227 {
228         fstring servername = "";
229         fstring printername = "";
230         fstring sharename = "";
231         fstring portname = "";
232         fstring drivername = "";
233         fstring comment = "";
234         fstring location = "";
235         fstring sepfile = "";
236         fstring printprocessor = "";
237         fstring datatype = "";
238         fstring parameters = "";
239         
240         rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
241
242         rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
243
244         rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
245
246         rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
247
248         rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
249
250         rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
251
252         rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
253
254         rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
255
256         rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
257
258         rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
259
260         rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
261
262         printf("\tservername:[%s]\n", servername);
263         printf("\tprintername:[%s]\n", printername);
264         printf("\tsharename:[%s]\n", sharename);
265         printf("\tportname:[%s]\n", portname);
266         printf("\tdrivername:[%s]\n", drivername);
267         printf("\tcomment:[%s]\n", comment);
268         printf("\tlocation:[%s]\n", location);
269         printf("\tsepfile:[%s]\n", sepfile);
270         printf("\tprintprocessor:[%s]\n", printprocessor);
271         printf("\tdatatype:[%s]\n", datatype);
272         printf("\tparameters:[%s]\n", parameters);
273         printf("\tattributes:[0x%x]\n", i2->attributes);
274         printf("\tpriority:[0x%x]\n", i2->priority);
275         printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
276         printf("\tstarttime:[0x%x]\n", i2->starttime);
277         printf("\tuntiltime:[0x%x]\n", i2->untiltime);
278         printf("\tstatus:[0x%x]\n", i2->status);
279         printf("\tcjobs:[0x%x]\n", i2->cjobs);
280         printf("\taverageppm:[0x%x]\n", i2->averageppm);
281
282         if (i2->secdesc) 
283                 display_sec_desc(i2->secdesc);
284
285         printf("\n");
286 }
287
288 /****************************************************************************
289 printer info level 3 display function
290 ****************************************************************************/
291 static void display_print_info_3(PRINTER_INFO_3 *i3)
292 {
293         printf("\tflags:[0x%x]\n", i3->flags);
294
295         display_sec_desc(i3->secdesc);
296
297         printf("\n");
298 }
299
300 /* Enumerate printers */
301
302 static WERROR cmd_spoolss_enum_printers(struct cli_state *cli, 
303                                           TALLOC_CTX *mem_ctx,
304                                           int argc, const char **argv)
305 {
306         WERROR                  result;
307         uint32                  info_level = 1;
308         PRINTER_INFO_CTR        ctr;
309         uint32                  i = 0, num_printers, needed;
310         fstring name;
311
312         if (argc > 3) 
313         {
314                 printf("Usage: %s [level] [name]\n", argv[0]);
315                 return WERR_OK;
316         }
317
318         if (argc >= 2)
319                 info_level = atoi(argv[1]);
320
321         if (argc == 3)
322                 fstrcpy(name, argv[2]);
323         else {
324                 slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
325                 strupper_m(name);
326         }
327
328         /* Enumerate printers  -- Should we enumerate types other 
329            than PRINTER_ENUM_LOCAL?  Maybe accept as a parameter?  --jerry */
330
331         ZERO_STRUCT(ctr);
332
333         result = cli_spoolss_enum_printers(
334                 cli, mem_ctx, 0, &needed, name, PRINTER_ENUM_LOCAL, 
335                 info_level, &num_printers, &ctr);
336
337         if (W_ERROR_V(result) == ERRinsufficientbuffer)
338                 result = cli_spoolss_enum_printers(
339                         cli, mem_ctx, needed, NULL, name, PRINTER_ENUM_LOCAL, 
340                         info_level, &num_printers, &ctr);
341
342         if (W_ERROR_IS_OK(result)) {
343
344                 if (!num_printers) {
345                         printf ("No printers returned.\n");
346                         goto done;
347                 }
348         
349                 for (i = 0; i < num_printers; i++) {
350                         switch(info_level) {
351                         case 0:
352                                 display_print_info_0(&ctr.printers_0[i]);
353                                 break;
354                         case 1:
355                                 display_print_info_1(&ctr.printers_1[i]);
356                                 break;
357                         case 2:
358                                 display_print_info_2(&ctr.printers_2[i]);
359                                 break;
360                         case 3:
361                                 display_print_info_3(&ctr.printers_3[i]);
362                                 break;
363                         default:
364                                 printf("unknown info level %d\n", info_level);
365                                 goto done;
366                         }
367                 }
368         }
369         done:
370
371         return result;
372 }
373
374 /****************************************************************************
375 port info level 1 display function
376 ****************************************************************************/
377 static void display_port_info_1(PORT_INFO_1 *i1)
378 {
379         fstring buffer;
380         
381         rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
382         printf("\tPort Name:\t[%s]\n", buffer);
383 }
384
385 /****************************************************************************
386 port info level 2 display function
387 ****************************************************************************/
388 static void display_port_info_2(PORT_INFO_2 *i2)
389 {
390         fstring buffer;
391         
392         rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
393         printf("\tPort Name:\t[%s]\n", buffer);
394         rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
395
396         printf("\tMonitor Name:\t[%s]\n", buffer);
397         rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
398
399         printf("\tDescription:\t[%s]\n", buffer);
400         printf("\tPort Type:\t" );
401         if ( i2->port_type ) {
402                 int comma = 0; /* hack */
403                 printf( "[" );
404                 if ( i2->port_type & PORT_TYPE_READ ) {
405                         printf( "Read" );
406                         comma = 1;
407                 }
408                 if ( i2->port_type & PORT_TYPE_WRITE ) {
409                         printf( "%sWrite", comma ? ", " : "" );
410                         comma = 1;
411                 }
412                 /* These two have slightly different interpretations
413                  on 95/98/ME but I'm disregarding that for now */
414                 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
415                         printf( "%sRedirected", comma ? ", " : "" );
416                         comma = 1;
417                 }
418                 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
419                         printf( "%sNet-Attached", comma ? ", " : "" );
420                 }
421                 printf( "]\n" );
422         } else {
423                 printf( "[Unset]\n" );
424         }
425         printf("\tReserved:\t[%d]\n", i2->reserved);
426         printf("\n");
427 }
428
429 /* Enumerate ports */
430
431 static WERROR cmd_spoolss_enum_ports(struct cli_state *cli, 
432                                        TALLOC_CTX *mem_ctx, int argc, 
433                                        const char **argv)
434 {
435         WERROR                  result;
436         uint32                  needed, info_level = 1;
437         PORT_INFO_CTR           ctr;
438         uint32                  returned;
439         
440         if (argc > 2) {
441                 printf("Usage: %s [level]\n", argv[0]);
442                 return WERR_OK;
443         }
444         
445         if (argc == 2)
446                 info_level = atoi(argv[1]);
447
448         /* Enumerate ports */
449
450         ZERO_STRUCT(ctr);
451
452         result = cli_spoolss_enum_ports(cli, mem_ctx, 0, &needed, info_level, 
453                                         &returned, &ctr);
454
455         if (W_ERROR_V(result) == ERRinsufficientbuffer)
456                 result = cli_spoolss_enum_ports(cli, mem_ctx, needed, NULL,
457                                                 info_level, &returned, &ctr);
458
459         if (W_ERROR_IS_OK(result)) {
460                 int i;
461
462                 for (i = 0; i < returned; i++) {
463                         switch (info_level) {
464                         case 1:
465                                 display_port_info_1(&ctr.port.info_1[i]);
466                                 break;
467                         case 2:
468                                 display_port_info_2(&ctr.port.info_2[i]);
469                                 break;
470                         default:
471                                 printf("unknown info level %d\n", info_level);
472                                 break;
473                         }
474                 }
475         }
476         
477         return result;
478 }
479
480 /***********************************************************************
481  * Set printer comment - use a level2 set.
482  */
483 static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
484                                        TALLOC_CTX *mem_ctx,
485                                        int argc, const char **argv)
486 {
487         POLICY_HND      pol;
488         WERROR          result;
489         uint32          needed;
490         uint32          info_level = 2;
491         BOOL            opened_hnd = False;
492         PRINTER_INFO_CTR ctr;
493         fstring         printername,
494                         servername,
495                         user,
496                         comment;
497
498         if (argc == 1 || argc > 3) {
499                 printf("Usage: %s printername comment\n", argv[0]);
500
501                 return WERR_OK;
502         }
503
504         /* Open a printer handle */
505         if (argc == 3) {
506                 fstrcpy(comment, argv[2]);
507         }
508
509         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
510         strupper_m(servername);
511         fstrcpy(printername, argv[1]);
512         fstrcpy(user, cli->user_name);
513
514         /* get a printer handle */
515         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
516                                 PRINTER_ALL_ACCESS, servername,
517                                 user, &pol);
518                                 
519         if (!W_ERROR_IS_OK(result))
520                 goto done;
521
522         opened_hnd = True;
523
524         /* Get printer info */
525         result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
526
527         if (W_ERROR_V(result) == ERRinsufficientbuffer)
528                 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
529
530         if (!W_ERROR_IS_OK(result))
531                 goto done;
532
533
534         /* Modify the comment. */
535         init_unistr(&ctr.printers_2->comment, comment);
536         ctr.printers_2->devmode = NULL;
537         ctr.printers_2->secdesc = NULL;
538
539         result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
540         if (W_ERROR_IS_OK(result))
541                 printf("Success in setting comment.\n");
542
543  done:
544         if (opened_hnd)
545                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
546
547         return result;
548 }
549
550 /***********************************************************************
551  * Set printer name - use a level2 set.
552  */
553 static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
554                                        TALLOC_CTX *mem_ctx,
555                                        int argc, const char **argv)
556 {
557         POLICY_HND      pol;
558         WERROR          result;
559         uint32          needed;
560         uint32          info_level = 2;
561         BOOL            opened_hnd = False;
562         PRINTER_INFO_CTR ctr;
563         fstring         printername,
564                         servername,
565                         user,
566                         new_printername;
567
568         if (argc == 1 || argc > 3) {
569                 printf("Usage: %s printername new_printername\n", argv[0]);
570
571                 return WERR_OK;
572         }
573
574         /* Open a printer handle */
575         if (argc == 3) {
576                 fstrcpy(new_printername, argv[2]);
577         }
578
579         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
580         strupper_m(servername);
581         fstrcpy(printername, argv[1]);
582         fstrcpy(user, cli->user_name);
583
584         /* get a printer handle */
585         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
586                                 PRINTER_ALL_ACCESS, servername,
587                                 user, &pol);
588                                 
589         if (!W_ERROR_IS_OK(result))
590                 goto done;
591
592         opened_hnd = True;
593
594         /* Get printer info */
595         result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
596
597         if (W_ERROR_V(result) == ERRinsufficientbuffer)
598                 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
599
600         if (!W_ERROR_IS_OK(result))
601                 goto done;
602
603
604         /* Modify the printername. */
605         init_unistr(&ctr.printers_2->printername, new_printername);
606         ctr.printers_2->devmode = NULL;
607         ctr.printers_2->secdesc = NULL;
608
609         result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
610         if (W_ERROR_IS_OK(result))
611                 printf("Success in setting printername.\n");
612
613  done:
614         if (opened_hnd)
615                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
616
617         return result;
618 }
619
620 /***********************************************************************
621  * Get printer information
622  */
623 static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
624                                        TALLOC_CTX *mem_ctx,
625                                        int argc, const char **argv)
626 {
627         POLICY_HND      pol;
628         WERROR          result;
629         uint32          info_level = 1;
630         BOOL            opened_hnd = False;
631         PRINTER_INFO_CTR ctr;
632         fstring         printername,
633                         servername,
634                         user;
635         uint32 needed;
636
637         if (argc == 1 || argc > 3) {
638                 printf("Usage: %s <printername> [level]\n", argv[0]);
639                 return WERR_OK;
640         }
641
642         /* Open a printer handle */
643         if (argc == 3) {
644                 info_level = atoi(argv[2]);
645         }
646
647         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
648         strupper_m(servername);
649         slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
650         fstrcpy(user, cli->user_name);
651         
652         /* get a printer handle */
653
654         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
655                                              "", MAXIMUM_ALLOWED_ACCESS, 
656                                              servername, user, &pol);
657
658         if (!W_ERROR_IS_OK(result))
659                 goto done;
660  
661         opened_hnd = True;
662
663         /* Get printer info */
664
665         result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
666                                         &pol, info_level, &ctr);
667
668         if (W_ERROR_V(result) == ERRinsufficientbuffer)
669                 result = cli_spoolss_getprinter(
670                         cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
671
672         if (!W_ERROR_IS_OK(result))
673                 goto done;
674
675         /* Display printer info */
676
677         switch (info_level) {
678         case 0: 
679                 display_print_info_0(ctr.printers_0);
680                 break;
681         case 1:
682                 display_print_info_1(ctr.printers_1);
683                 break;
684         case 2:
685                 display_print_info_2(ctr.printers_2);
686                 break;
687         case 3:
688                 display_print_info_3(ctr.printers_3);
689                 break;
690         default:
691                 printf("unknown info level %d\n", info_level);
692                 break;
693         }
694
695  done: 
696         if (opened_hnd) 
697                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
698
699         return result;
700 }
701
702 static void display_reg_value(REGISTRY_VALUE value)
703 {
704         pstring text;
705
706         switch(value.type) {
707         case REG_DWORD:
708                 printf("%s: REG_DWORD: 0x%08x\n", value.valuename, 
709                        *((uint32 *) value.data_p));
710                 break;
711         case REG_SZ:
712                 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
713                             STR_TERMINATE);
714                 printf("%s: REG_SZ: %s\n", value.valuename, text);
715                 break;
716         case REG_BINARY:
717                 printf("%s: REG_BINARY: unknown length value not displayed\n",
718                        value.valuename);
719                 break;
720         case REG_MULTI_SZ: {
721                 uint16 *curstr = (uint16 *) value.data_p;
722                 uint8 *start = value.data_p;
723                 printf("%s: REG_MULTI_SZ:\n", value.valuename);
724                 while ((*curstr != 0) && 
725                        ((uint8 *) curstr < start + value.size)) {
726                         rpcstr_pull(text, curstr, sizeof(text), -1, 
727                                     STR_TERMINATE);
728                         printf("  %s\n", text);
729                         curstr += strlen(text) + 1;
730                 }
731         }
732         break;
733         default:
734                 printf("%s: unknown type %d\n", value.valuename, value.type);
735         }
736         
737 }
738
739 /***********************************************************************
740  * Get printer data
741  */
742 static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
743                                            TALLOC_CTX *mem_ctx,
744                                            int argc, const char **argv)
745 {
746         POLICY_HND      pol;
747         WERROR          result;
748         BOOL            opened_hnd = False;
749         fstring         printername,
750                         servername,
751                         user;
752         uint32 needed;
753         const char *valuename;
754         REGISTRY_VALUE value;
755
756         if (argc != 3) {
757                 printf("Usage: %s <printername> <valuename>\n", argv[0]);
758                 printf("<printername> of . queries print server\n");
759                 return WERR_OK;
760         }
761         valuename = argv[2];
762
763         /* Open a printer handle */
764
765         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
766         strupper_m(servername);
767         if (strncmp(argv[1], ".", sizeof(".")) == 0)
768                 fstrcpy(printername, servername);
769         else
770                 slprintf(printername, sizeof(servername)-1, "%s\\%s", 
771                           servername, argv[1]);
772         fstrcpy(user, cli->user_name);
773         
774         /* get a printer handle */
775
776         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
777                                              "", MAXIMUM_ALLOWED_ACCESS, 
778                                              servername, user, &pol);
779
780         if (!W_ERROR_IS_OK(result))
781                 goto done;
782  
783         opened_hnd = True;
784
785         /* Get printer info */
786
787         result = cli_spoolss_getprinterdata(cli, mem_ctx, 0, &needed,
788                                             &pol, valuename, &value);
789
790         if (W_ERROR_V(result) == ERRmoredata)
791                 result = cli_spoolss_getprinterdata(
792                         cli, mem_ctx, needed, NULL, &pol, valuename, &value);
793
794         if (!W_ERROR_IS_OK(result))
795                 goto done;
796
797         /* Display printer data */
798
799         fstrcpy(value.valuename, valuename);
800         display_reg_value(value);
801         
802
803  done: 
804         if (opened_hnd) 
805                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
806
807         return result;
808 }
809
810 /***********************************************************************
811  * Get printer data
812  */
813 static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
814                                              TALLOC_CTX *mem_ctx,
815                                              int argc, const char **argv)
816 {
817         POLICY_HND      pol;
818         WERROR          result;
819         BOOL            opened_hnd = False;
820         fstring         printername,
821                         servername,
822                         user;
823         uint32 needed;
824         const char *valuename, *keyname;
825         REGISTRY_VALUE value;
826
827         if (argc != 4) {
828                 printf("Usage: %s <printername> <keyname> <valuename>\n", 
829                        argv[0]);
830                 printf("<printername> of . queries print server\n");
831                 return WERR_OK;
832         }
833         valuename = argv[3];
834         keyname = argv[2];
835
836         /* Open a printer handle */
837
838         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
839         strupper_m(servername);
840         if (strncmp(argv[1], ".", sizeof(".")) == 0)
841                 fstrcpy(printername, servername);
842         else
843                 slprintf(printername, sizeof(printername)-1, "%s\\%s", 
844                           servername, argv[1]);
845         fstrcpy(user, cli->user_name);
846         
847         /* get a printer handle */
848
849         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
850                                              "", MAXIMUM_ALLOWED_ACCESS, 
851                                              servername, user, &pol);
852
853         if (!W_ERROR_IS_OK(result))
854                 goto done;
855  
856         opened_hnd = True;
857
858         /* Get printer info */
859
860         result = cli_spoolss_getprinterdataex(cli, mem_ctx, 0, &needed,
861                                               &pol, keyname, valuename, 
862                                               &value);
863
864         if (W_ERROR_V(result) == ERRmoredata)
865                 result = cli_spoolss_getprinterdataex(cli, mem_ctx, needed, 
866                                                       NULL, &pol, keyname,
867                                                       valuename, &value);
868
869         if (!W_ERROR_IS_OK(result))
870                 goto done;
871
872         /* Display printer data */
873
874         fstrcpy(value.valuename, valuename);
875         display_reg_value(value);
876         
877
878  done: 
879         if (opened_hnd) 
880                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
881
882         return result;
883 }
884
885 /****************************************************************************
886 printer info level 0 display function
887 ****************************************************************************/
888 static void display_print_driver_1(DRIVER_INFO_1 *i1)
889 {
890         fstring name;
891         if (i1 == NULL)
892                 return;
893
894         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
895
896         printf ("Printer Driver Info 1:\n");
897         printf ("\tDriver Name: [%s]\n\n", name);
898         
899         return;
900 }
901
902 /****************************************************************************
903 printer info level 1 display function
904 ****************************************************************************/
905 static void display_print_driver_2(DRIVER_INFO_2 *i1)
906 {
907         fstring name;
908         fstring architecture;
909         fstring driverpath;
910         fstring datafile;
911         fstring configfile;
912         if (i1 == NULL)
913                 return;
914
915         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
916         rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
917         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
918         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
919         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
920
921         printf ("Printer Driver Info 2:\n");
922         printf ("\tVersion: [%x]\n", i1->version);
923         printf ("\tDriver Name: [%s]\n", name);
924         printf ("\tArchitecture: [%s]\n", architecture);
925         printf ("\tDriver Path: [%s]\n", driverpath);
926         printf ("\tDatafile: [%s]\n", datafile);
927         printf ("\tConfigfile: [%s]\n\n", configfile);
928
929         return;
930 }
931
932 /****************************************************************************
933 printer info level 2 display function
934 ****************************************************************************/
935 static void display_print_driver_3(DRIVER_INFO_3 *i1)
936 {
937         fstring name = "";
938         fstring architecture = "";
939         fstring driverpath = "";
940         fstring datafile = "";
941         fstring configfile = "";
942         fstring helpfile = "";
943         fstring dependentfiles = "";
944         fstring monitorname = "";
945         fstring defaultdatatype = "";
946         
947         int length=0;
948         BOOL valid = True;
949         
950         if (i1 == NULL)
951                 return;
952
953         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
954         rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
955         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
956         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
957         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
958         rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
959         rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
960         rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
961
962         printf ("Printer Driver Info 3:\n");
963         printf ("\tVersion: [%x]\n", i1->version);
964         printf ("\tDriver Name: [%s]\n",name);
965         printf ("\tArchitecture: [%s]\n", architecture);
966         printf ("\tDriver Path: [%s]\n", driverpath);
967         printf ("\tDatafile: [%s]\n", datafile);
968         printf ("\tConfigfile: [%s]\n", configfile);
969         printf ("\tHelpfile: [%s]\n\n", helpfile);
970
971         while (valid)
972         {
973                 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
974                 
975                 length+=strlen(dependentfiles)+1;
976                 
977                 if (strlen(dependentfiles) > 0)
978                 {
979                         printf ("\tDependentfiles: [%s]\n", dependentfiles);
980                 }
981                 else
982                 {
983                         valid = False;
984                 }
985         }
986         
987         printf ("\n");
988
989         printf ("\tMonitorname: [%s]\n", monitorname);
990         printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
991
992         return; 
993 }
994
995 /***********************************************************************
996  * Get printer information
997  */
998 static WERROR cmd_spoolss_getdriver(struct cli_state *cli, 
999                                       TALLOC_CTX *mem_ctx,
1000                                       int argc, const char **argv)
1001 {
1002         POLICY_HND      pol;
1003         WERROR          werror;
1004         uint32          info_level = 3;
1005         BOOL            opened_hnd = False;
1006         PRINTER_DRIVER_CTR      ctr;
1007         fstring         printername, 
1008                         servername, 
1009                         user;
1010         uint32          i;
1011         BOOL            success = False;
1012
1013         if ((argc == 1) || (argc > 3)) 
1014         {
1015                 printf("Usage: %s <printername> [level]\n", argv[0]);
1016                 return WERR_OK;
1017         }
1018
1019         /* get the arguments need to open the printer handle */
1020         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1021         strupper_m(servername);
1022         fstrcpy(user, cli->user_name);
1023         fstrcpy(printername, argv[1]);
1024         if (argc == 3)
1025                 info_level = atoi(argv[2]);
1026
1027         /* Open a printer handle */
1028
1029         werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
1030                                              PRINTER_ACCESS_USE,
1031                                              servername, user, &pol);
1032
1033         if (!W_ERROR_IS_OK(werror)) {
1034                 printf("Error opening printer handle for %s!\n", printername);
1035                 return werror;
1036         }
1037
1038         opened_hnd = True;
1039
1040         /* loop through and print driver info level for each architecture */
1041
1042         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1043                 uint32 needed;
1044
1045                 werror = cli_spoolss_getprinterdriver(
1046                         cli, mem_ctx, 0, &needed, &pol, info_level, 
1047                         archi_table[i].long_archi, archi_table[i].version,
1048                         &ctr);
1049
1050                 if (W_ERROR_V(werror) == ERRinsufficientbuffer) {
1051                         werror = cli_spoolss_getprinterdriver(
1052                                 cli, mem_ctx, needed, NULL, &pol, info_level, 
1053                                 archi_table[i].long_archi, archi_table[i].version, 
1054                                 &ctr);
1055                 }
1056
1057                 if (!W_ERROR_IS_OK(werror))
1058                         continue;
1059                 
1060                 /* need at least one success */
1061                 
1062                 success = True;
1063                         
1064                 printf ("\n[%s]\n", archi_table[i].long_archi);
1065
1066                 switch (info_level) {
1067                 case 1:
1068                         display_print_driver_1 (ctr.info1);
1069                         break;
1070                 case 2:
1071                         display_print_driver_2 (ctr.info2);
1072                         break;
1073                 case 3:
1074                         display_print_driver_3 (ctr.info3);
1075                         break;
1076                 default:
1077                         printf("unknown info level %d\n", info_level);
1078                         break;
1079                 }
1080         }
1081         
1082         /* Cleanup */
1083
1084         if (opened_hnd)
1085                 cli_spoolss_close_printer (cli, mem_ctx, &pol);
1086         
1087         if ( success )
1088                 werror = WERR_OK;
1089                 
1090         return werror;
1091 }
1092
1093 /***********************************************************************
1094  * Get printer information
1095  */
1096 static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli, 
1097                                          TALLOC_CTX *mem_ctx,
1098                                          int argc, const char **argv)
1099 {
1100         WERROR werror;
1101         uint32          info_level = 1;
1102         PRINTER_DRIVER_CTR      ctr;
1103         uint32          i, j,
1104                         returned;
1105
1106         if (argc > 2) 
1107         {
1108                 printf("Usage: enumdrivers [level]\n");
1109                 return WERR_OK;
1110         }
1111
1112         if (argc == 2)
1113                 info_level = atoi(argv[1]);
1114
1115
1116         /* loop through and print driver info level for each architecture */
1117         for (i=0; archi_table[i].long_archi!=NULL; i++) 
1118         {
1119                 uint32 needed;
1120
1121                 werror = cli_spoolss_enumprinterdrivers(
1122                         cli, mem_ctx, 0, &needed, info_level, 
1123                         archi_table[i].long_archi, &returned, &ctr);
1124
1125                 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1126                         werror = cli_spoolss_enumprinterdrivers(
1127                                 cli, mem_ctx, needed, NULL, info_level, 
1128                                 archi_table[i].long_archi, &returned, &ctr);
1129
1130                 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1131                         printf ("Server does not support environment [%s]\n", 
1132                                 archi_table[i].long_archi);
1133                         werror = WERR_OK;
1134                         continue;
1135                 }
1136
1137                 if (returned == 0)
1138                         continue;
1139                         
1140                 if (!W_ERROR_IS_OK(werror)) {
1141                         printf ("Error getting driver for environment [%s] - %d\n",
1142                                 archi_table[i].long_archi, W_ERROR_V(werror));
1143                         continue;
1144                 }
1145                 
1146                 printf ("\n[%s]\n", archi_table[i].long_archi);
1147                 switch (info_level) 
1148                 {
1149                         
1150                 case 1:
1151                         for (j=0; j < returned; j++) {
1152                                 display_print_driver_1 (&(ctr.info1[j]));
1153                         }
1154                         break;
1155                 case 2:
1156                         for (j=0; j < returned; j++) {
1157                                 display_print_driver_2 (&(ctr.info2[j]));
1158                         }
1159                         break;
1160                 case 3:
1161                         for (j=0; j < returned; j++) {
1162                                 display_print_driver_3 (&(ctr.info3[j]));
1163                         }
1164                         break;
1165                 default:
1166                         printf("unknown info level %d\n", info_level);
1167                         break;
1168                 }
1169         }
1170         
1171         return werror;
1172 }
1173
1174 /****************************************************************************
1175 printer info level 1 display function
1176 ****************************************************************************/
1177 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1178 {
1179         fstring name;
1180         if (i1 == NULL)
1181                 return;
1182  
1183         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1184  
1185         printf ("\tDirectory Name:[%s]\n", name);
1186 }
1187
1188 /***********************************************************************
1189  * Get printer driver directory information
1190  */
1191 static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli, 
1192                                          TALLOC_CTX *mem_ctx,
1193                                          int argc, const char **argv)
1194 {
1195         WERROR result;
1196         fstring                 env;
1197         DRIVER_DIRECTORY_CTR    ctr;
1198         uint32 needed;
1199
1200         if (argc > 2) {
1201                 printf("Usage: %s [environment]\n", argv[0]);
1202                 return WERR_OK;
1203         }
1204
1205         /* Get the arguments need to open the printer handle */
1206
1207         if (argc == 2)
1208                 fstrcpy (env, argv[1]);
1209         else
1210                 fstrcpy (env, "Windows NT x86");
1211
1212         /* Get the directory.  Only use Info level 1 */
1213
1214         result = cli_spoolss_getprinterdriverdir(
1215                 cli, mem_ctx, 0, &needed, 1, env, &ctr);
1216
1217         if (W_ERROR_V(result) == ERRinsufficientbuffer)
1218                 result = cli_spoolss_getprinterdriverdir(
1219                         cli, mem_ctx, needed, NULL, 1, env, &ctr);
1220
1221         if (W_ERROR_IS_OK(result))
1222                 display_printdriverdir_1(ctr.info1);
1223
1224         return result;
1225 }
1226
1227 /*******************************************************************************
1228  set the version and environment fields of a DRIVER_INFO_3 struct
1229  ******************************************************************************/
1230 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1231 {
1232
1233         int i;
1234         
1235         for (i=0; archi_table[i].long_archi != NULL; i++) 
1236         {
1237                 if (strcmp(arch, archi_table[i].short_archi) == 0)
1238                 {
1239                         info->version = archi_table[i].version;
1240                         init_unistr (&info->architecture, archi_table[i].long_archi);
1241                         break;
1242                 }
1243         }
1244         
1245         if (archi_table[i].long_archi == NULL)
1246         {
1247                 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1248         }
1249         
1250         return;
1251 }
1252
1253
1254 /**************************************************************************
1255  wrapper for strtok to get the next parameter from a delimited list.
1256  Needed to handle the empty parameter string denoted by "NULL"
1257  *************************************************************************/
1258 static char* get_driver_3_param (const char* str, const char* delim, UNISTR* dest)
1259 {
1260         char    *ptr;
1261
1262         /* get the next token */
1263         ptr = strtok(str, delim);
1264
1265         /* a string of 'NULL' is used to represent an empty
1266            parameter because two consecutive delimiters
1267            will not return an empty string.  See man strtok(3)
1268            for details */
1269         if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1270                 ptr = NULL;
1271
1272         if (dest != NULL)
1273                 init_unistr(dest, ptr); 
1274
1275         return ptr;
1276 }
1277
1278 /********************************************************************************
1279  fill in the members of a DRIVER_INFO_3 struct using a character 
1280  string in the form of
1281          <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1282              <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1283              <Default Data Type>:<Comma Separated list of Files> 
1284  *******************************************************************************/
1285 static BOOL init_drv_info_3_members (
1286         TALLOC_CTX *mem_ctx, 
1287         DRIVER_INFO_3 *info, 
1288         const char *args
1289 )
1290 {
1291         char    *str, *str2;
1292         uint32  len, i;
1293         
1294         /* fill in the UNISTR fields */
1295         str = get_driver_3_param (args, ":", &info->name);
1296         str = get_driver_3_param (NULL, ":", &info->driverpath);
1297         str = get_driver_3_param (NULL, ":", &info->datafile);
1298         str = get_driver_3_param (NULL, ":", &info->configfile);
1299         str = get_driver_3_param (NULL, ":", &info->helpfile);
1300         str = get_driver_3_param (NULL, ":", &info->monitorname);
1301         str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1302
1303         /* <Comma Separated List of Dependent Files> */
1304         str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1305         str = str2;                     
1306
1307         /* begin to strip out each filename */
1308         str = strtok(str, ",");         
1309         len = 0;
1310         while (str != NULL)
1311         {
1312                 /* keep a cumlative count of the str lengths */
1313                 len += strlen(str)+1;
1314                 str = strtok(NULL, ",");
1315         }
1316
1317         /* allocate the space; add one extra slot for a terminating NULL.
1318            Each filename is NULL terminated and the end contains a double
1319            NULL */
1320         if ((info->dependentfiles=(uint16*)talloc(mem_ctx, (len+1)*sizeof(uint16))) == NULL)
1321         {
1322                 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1323                 return False;
1324         }
1325         for (i=0; i<len; i++)
1326         {
1327                 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1328         }
1329         info->dependentfiles[len] = '\0';
1330
1331         return True;
1332 }
1333
1334
1335 static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, 
1336                                              TALLOC_CTX *mem_ctx,
1337                                              int argc, const char **argv)
1338 {
1339         WERROR result;
1340         uint32                  level = 3;
1341         PRINTER_DRIVER_CTR      ctr;
1342         DRIVER_INFO_3           info3;
1343         const char              *arch;
1344         fstring                 driver_name;
1345
1346         /* parse the command arguements */
1347         if (argc != 3 && argc != 4)
1348         {
1349                 printf ("Usage: %s <Environment> \\\n", argv[0]);
1350                 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1351                 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1352                 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1353                 printf ("\t[version]\n");
1354
1355             return WERR_OK;
1356         }
1357                 
1358         /* Fill in the DRIVER_INFO_3 struct */
1359         ZERO_STRUCT(info3);
1360         if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1361         {
1362                 printf ("Error Unknown architechture [%s]\n", argv[1]);
1363                 return WERR_INVALID_PARAM;
1364         }
1365         else
1366                 set_drv_info_3_env(&info3, arch);
1367
1368         if (!init_drv_info_3_members(mem_ctx, &info3, argv[2]))
1369         {
1370                 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1371                 return WERR_INVALID_PARAM;
1372         }
1373
1374         /* if printer driver version specified, override the default version
1375          * used by the architecture.  This allows installation of Windows
1376          * 2000 (version 3) printer drivers. */
1377         if (argc == 4)
1378         {
1379                 info3.version = atoi(argv[3]);
1380         }
1381
1382
1383         ctr.info3 = &info3;
1384         result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1385
1386         if (W_ERROR_IS_OK(result)) {
1387                 rpcstr_pull(driver_name, info3.name.buffer, 
1388                             sizeof(driver_name), -1, STR_TERMINATE);
1389                 printf ("Printer Driver %s successfully installed.\n",
1390                         driver_name);
1391         }
1392
1393         return result;
1394 }
1395
1396
1397 static WERROR cmd_spoolss_addprinterex(struct cli_state *cli, 
1398                                          TALLOC_CTX *mem_ctx,
1399                                          int argc, const char **argv)
1400 {
1401         WERROR result;
1402         uint32                  level = 2;
1403         PRINTER_INFO_CTR        ctr;
1404         PRINTER_INFO_2          info2;
1405         fstring                 servername;
1406         
1407         /* parse the command arguements */
1408         if (argc != 5)
1409         {
1410                 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1411                 return WERR_OK;
1412         }
1413         
1414         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1415         strupper_m(servername);
1416
1417         /* Fill in the DRIVER_INFO_2 struct */
1418         ZERO_STRUCT(info2);
1419 #if 0   /* JERRY */
1420         init_unistr( &info2.servername,         servername);
1421 #endif
1422         init_unistr( &info2.printername,        argv[1]);
1423         init_unistr( &info2.sharename,          argv[2]);
1424         init_unistr( &info2.drivername,         argv[3]);
1425         init_unistr( &info2.portname,           argv[4]);
1426         init_unistr( &info2.comment,            "Created by rpcclient");
1427         init_unistr( &info2.printprocessor,     "winprint");
1428         init_unistr( &info2.datatype,           "RAW");
1429         info2.devmode =         NULL;
1430         info2.secdesc =         NULL;
1431         info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
1432         info2.priority          = 0;
1433         info2.defaultpriority   = 0;
1434         info2.starttime         = 0;
1435         info2.untiltime         = 0;
1436         
1437         /* These three fields must not be used by AddPrinter() 
1438            as defined in the MS Platform SDK documentation..  
1439            --jerry
1440         info2.status            = 0;
1441         info2.cjobs             = 0;
1442         info2.averageppm        = 0;
1443         */
1444
1445         ctr.printers_2 = &info2;
1446         result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1447
1448         if (W_ERROR_IS_OK(result))
1449                 printf ("Printer %s successfully installed.\n", argv[1]);
1450
1451         return result;
1452 }
1453
1454 static WERROR cmd_spoolss_setdriver(struct cli_state *cli, 
1455                                       TALLOC_CTX *mem_ctx,
1456                                       int argc, const char **argv)
1457 {
1458         POLICY_HND              pol;
1459         WERROR                  result;
1460         uint32                  level = 2;
1461         BOOL                    opened_hnd = False;
1462         PRINTER_INFO_CTR        ctr;
1463         PRINTER_INFO_2          info2;
1464         fstring                 servername,
1465                                 printername,
1466                                 user;
1467         uint32 needed;
1468         
1469         /* parse the command arguements */
1470         if (argc != 3)
1471         {
1472                 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1473                 return WERR_OK;
1474         }
1475
1476         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1477         strupper_m(servername);
1478         slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1479         fstrcpy(user, cli->user_name);
1480
1481         /* Get a printer handle */
1482
1483         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
1484                                              PRINTER_ALL_ACCESS,
1485                                              servername, user, &pol);
1486
1487         if (!W_ERROR_IS_OK(result))
1488                 goto done;
1489
1490         opened_hnd = True;
1491
1492         /* Get printer info */
1493
1494         ZERO_STRUCT (info2);
1495         ctr.printers_2 = &info2;
1496
1497         result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
1498                                         &pol, level, &ctr);
1499
1500         if (W_ERROR_V(result) == ERRinsufficientbuffer)
1501                 result = cli_spoolss_getprinter(
1502                         cli, mem_ctx, needed, NULL, &pol, level, &ctr);
1503
1504         if (!W_ERROR_IS_OK(result)) {
1505                 printf ("Unable to retrieve printer information!\n");
1506                 goto done;
1507         }
1508
1509         /* Set the printer driver */
1510
1511         init_unistr(&ctr.printers_2->drivername, argv[2]);
1512
1513         result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1514
1515         if (!W_ERROR_IS_OK(result)) {
1516                 printf("SetPrinter call failed!\n");
1517                 goto done;;
1518         }
1519
1520         printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1521
1522 done:
1523         /* Cleanup */
1524
1525         if (opened_hnd)
1526                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
1527
1528         return result;
1529 }
1530
1531
1532 static WERROR cmd_spoolss_deletedriver(struct cli_state *cli, 
1533                                          TALLOC_CTX *mem_ctx,
1534                                          int argc, const char **argv)
1535 {
1536         WERROR result;
1537         fstring                 servername;
1538         int                     i;
1539         
1540         /* parse the command arguements */
1541         if (argc != 2)
1542         {
1543                 printf ("Usage: %s <driver>\n", argv[0]);
1544                 return WERR_OK;
1545         }
1546
1547         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1548         strupper_m(servername);
1549
1550         /* delete the driver for all architectures */
1551         for (i=0; archi_table[i].long_archi; i++)
1552         {
1553                 /* make the call to remove the driver */
1554                 result = cli_spoolss_deleteprinterdriver(
1555                         cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1556
1557                 if ( !W_ERROR_IS_OK(result) ) {
1558                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1559                                 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n", 
1560                                         argv[1], archi_table[i].long_archi, 
1561                                         W_ERROR_V(result));
1562                         }
1563                 } 
1564                 else 
1565                 {
1566                         printf ("Driver %s removed for arch [%s].\n", argv[1], 
1567                                 archi_table[i].long_archi);
1568                 }
1569         }
1570                 
1571         return result;
1572 }
1573
1574 static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli, 
1575                                             TALLOC_CTX *mem_ctx,
1576                                             int argc, const char **argv)
1577 {
1578         WERROR result;
1579         char *servername = NULL, *environment = NULL;
1580         fstring procdir;
1581         uint32 needed;
1582         
1583         /* parse the command arguements */
1584         if (argc > 2) {
1585                 printf ("Usage: %s [environment]\n", argv[0]);
1586                 return WERR_OK;
1587         }
1588
1589         if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
1590                 return WERR_NOMEM;
1591         strupper_m(servername);
1592
1593         if (asprintf(&environment, "%s", (argc == 2) ? argv[1] : 
1594                      PRINTER_DRIVER_ARCHITECTURE) < 0) {
1595                 SAFE_FREE(servername);
1596                 return WERR_NOMEM;
1597         }
1598
1599         result = cli_spoolss_getprintprocessordirectory(
1600                 cli, mem_ctx, 0, &needed, servername, environment, procdir);
1601
1602         if (W_ERROR_V(result) == ERRinsufficientbuffer)
1603                 result = cli_spoolss_getprintprocessordirectory(
1604                         cli, mem_ctx, needed, NULL, servername, environment, 
1605                         procdir);
1606
1607         if (W_ERROR_IS_OK(result))
1608                 printf("%s\n", procdir);
1609
1610         SAFE_FREE(servername);
1611         SAFE_FREE(environment);
1612
1613         return result;
1614 }
1615
1616 /* Add a form */
1617
1618 static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1619                                     int argc, const char **argv)
1620 {
1621         POLICY_HND handle;
1622         WERROR werror;
1623         char *servername = NULL, *printername = NULL;
1624         FORM form;
1625         BOOL got_handle = False;
1626         
1627         /* Parse the command arguements */
1628
1629         if (argc != 3) {
1630                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1631                 return WERR_OK;
1632         }
1633         
1634         /* Get a printer handle */
1635
1636         asprintf(&servername, "\\\\%s", cli->desthost);
1637         strupper_m(servername);
1638         asprintf(&printername, "%s\\%s", servername, argv[1]);
1639
1640         werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
1641                                              MAXIMUM_ALLOWED_ACCESS, 
1642                                              servername, cli->user_name, &handle);
1643
1644         if (!W_ERROR_IS_OK(werror))
1645                 goto done;
1646
1647         got_handle = True;
1648
1649         /* Dummy up some values for the form data */
1650
1651         form.flags = FORM_USER;
1652         form.size_x = form.size_y = 100;
1653         form.left = 0;
1654         form.top = 10;
1655         form.right = 20;
1656         form.bottom = 30;
1657
1658         init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1659
1660         /* Add the form */
1661
1662
1663         werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1664
1665  done:
1666         if (got_handle)
1667                 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1668
1669         SAFE_FREE(servername);
1670         SAFE_FREE(printername);
1671
1672         return werror;
1673 }
1674
1675 /* Set a form */
1676
1677 static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1678                                     int argc, const char **argv)
1679 {
1680         POLICY_HND handle;
1681         WERROR werror;
1682         char *servername = NULL, *printername = NULL;
1683         FORM form;
1684         BOOL got_handle = False;
1685         
1686         /* Parse the command arguements */
1687
1688         if (argc != 3) {
1689                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1690                 return WERR_OK;
1691         }
1692         
1693         /* Get a printer handle */
1694
1695         asprintf(&servername, "\\\\%s", cli->desthost);
1696         strupper_m(servername);
1697         asprintf(&printername, "%s\\%s", servername, argv[1]);
1698
1699         werror = cli_spoolss_open_printer_ex(
1700                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
1701                 servername, cli->user_name, &handle);
1702
1703         if (!W_ERROR_IS_OK(werror))
1704                 goto done;
1705
1706         got_handle = True;
1707
1708         /* Dummy up some values for the form data */
1709
1710         form.flags = FORM_PRINTER;
1711         form.size_x = form.size_y = 100;
1712         form.left = 0;
1713         form.top = 1000;
1714         form.right = 2000;
1715         form.bottom = 3000;
1716
1717         init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1718
1719         /* Set the form */
1720
1721         werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1722
1723  done:
1724         if (got_handle)
1725                 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1726
1727         SAFE_FREE(servername);
1728         SAFE_FREE(printername);
1729
1730         return werror;
1731 }
1732
1733 /* Get a form */
1734
1735 static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1736                                     int argc, const char **argv)
1737 {
1738         POLICY_HND handle;
1739         WERROR werror;
1740         char *servername = NULL, *printername = NULL;
1741         FORM_1 form;
1742         BOOL got_handle = False;
1743         uint32 needed;
1744         
1745         /* Parse the command arguements */
1746
1747         if (argc != 3) {
1748                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1749                 return WERR_OK;
1750         }
1751         
1752         /* Get a printer handle */
1753
1754         asprintf(&servername, "\\\\%s", cli->desthost);
1755         strupper_m(servername);
1756         asprintf(&printername, "%s\\%s", servername, argv[1]);
1757
1758         werror = cli_spoolss_open_printer_ex(
1759                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
1760                 servername, cli->user_name, &handle);
1761
1762         if (!W_ERROR_IS_OK(werror))
1763                 goto done;
1764
1765         got_handle = True;
1766
1767         /* Set the form */
1768
1769         werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed,
1770                                      &handle, argv[2], 1, &form);
1771
1772         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1773                 werror = cli_spoolss_getform(cli, mem_ctx, needed, NULL,
1774                                              &handle, argv[2], 1, &form);
1775
1776         if (!W_ERROR_IS_OK(werror))
1777                 goto done;
1778
1779         printf("width: %d\n", form.width);
1780         printf("length: %d\n", form.length);
1781         printf("left: %d\n", form.left);
1782         printf("top: %d\n", form.top);
1783         printf("right: %d\n", form.right);
1784         printf("bottom: %d\n", form.bottom);
1785
1786  done:
1787         if (got_handle)
1788                 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1789
1790         SAFE_FREE(servername);
1791         SAFE_FREE(printername);
1792
1793         return werror;
1794 }
1795
1796 /* Delete a form */
1797
1798 static WERROR cmd_spoolss_deleteform(struct cli_state *cli, 
1799                                        TALLOC_CTX *mem_ctx, int argc, 
1800                                        const char **argv)
1801 {
1802         POLICY_HND handle;
1803         WERROR werror;
1804         char *servername = NULL, *printername = NULL;
1805         BOOL got_handle = False;
1806         
1807         /* Parse the command arguements */
1808
1809         if (argc != 3) {
1810                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1811                 return WERR_OK;
1812         }
1813         
1814         /* Get a printer handle */
1815
1816         asprintf(&servername, "\\\\%s", cli->desthost);
1817         strupper_m(servername);
1818         asprintf(&printername, "%s\\%s", servername, argv[1]);
1819
1820         werror = cli_spoolss_open_printer_ex(
1821                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
1822                 servername, cli->user_name, &handle);
1823
1824         if (!W_ERROR_IS_OK(werror))
1825                 goto done;
1826
1827         got_handle = True;
1828
1829         /* Delete the form */
1830
1831         werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1832
1833  done:
1834         if (got_handle)
1835                 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1836
1837         SAFE_FREE(servername);
1838         SAFE_FREE(printername);
1839
1840         return werror;
1841 }
1842
1843 /* Enumerate forms */
1844
1845 static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, 
1846                                        TALLOC_CTX *mem_ctx, int argc, 
1847                                        const char **argv)
1848 {
1849         POLICY_HND handle;
1850         WERROR werror;
1851         char *servername = NULL, *printername = NULL;
1852         BOOL got_handle = False;
1853         uint32 needed, num_forms, level = 1, i;
1854         FORM_1 *forms;
1855         
1856         /* Parse the command arguements */
1857
1858         if (argc != 2) {
1859                 printf ("Usage: %s <printer>\n", argv[0]);
1860                 return WERR_OK;
1861         }
1862         
1863         /* Get a printer handle */
1864
1865         asprintf(&servername, "\\\\%s", cli->desthost);
1866         strupper_m(servername);
1867         asprintf(&printername, "%s\\%s", servername, argv[1]);
1868
1869         werror = cli_spoolss_open_printer_ex(
1870                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
1871                 servername, cli->user_name, &handle);
1872
1873         if (!W_ERROR_IS_OK(werror))
1874                 goto done;
1875
1876         got_handle = True;
1877
1878         /* Enumerate forms */
1879
1880         werror = cli_spoolss_enumforms(
1881                 cli, mem_ctx, 0, &needed, &handle, level, &num_forms, &forms);
1882
1883         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1884                 werror = cli_spoolss_enumforms(
1885                         cli, mem_ctx, needed, NULL, &handle, level, 
1886                         &num_forms, &forms);
1887
1888         if (!W_ERROR_IS_OK(werror))
1889                 goto done;
1890
1891         /* Display output */
1892
1893         for (i = 0; i < num_forms; i++) {
1894                 fstring form_name;
1895
1896                 if (forms[i].name.buffer)
1897                         rpcstr_pull(form_name, forms[i].name.buffer,
1898                                     sizeof(form_name), -1, STR_TERMINATE);
1899
1900                 printf("%s\n", form_name);
1901         }
1902
1903  done:
1904         if (got_handle)
1905                 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1906
1907         SAFE_FREE(servername);
1908         SAFE_FREE(printername);
1909
1910         return werror;
1911 }
1912
1913 static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
1914                                             TALLOC_CTX *mem_ctx,
1915                                             int argc, const char **argv)
1916 {
1917         WERROR result;
1918         uint32 needed;
1919         fstring servername, printername, user;
1920         POLICY_HND pol;
1921         BOOL opened_hnd = False;
1922         PRINTER_INFO_CTR ctr;
1923         PRINTER_INFO_0 info;
1924         REGISTRY_VALUE value;
1925         UNISTR2 data;
1926
1927         /* parse the command arguements */
1928         if (argc != 4) {
1929                 printf ("Usage: %s <printer> <value> <data>\n", argv[0]);
1930                 return WERR_OK;
1931         }
1932
1933         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1934         strupper_m(servername);
1935         slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1936         fstrcpy(user, cli->user_name);
1937
1938         /* get a printer handle */
1939         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1940                                              MAXIMUM_ALLOWED_ACCESS, servername, 
1941                                              user, &pol);
1942         if (!W_ERROR_IS_OK(result))
1943                 goto done;
1944
1945         opened_hnd = True;
1946
1947         ctr.printers_0 = &info;
1948
1949         result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
1950                                         &pol, 0, &ctr);
1951
1952         if (W_ERROR_V(result) == ERRinsufficientbuffer)
1953                 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
1954
1955         if (!W_ERROR_IS_OK(result))
1956                 goto done;
1957                 
1958         printf("%s\n", timestring(True));
1959         printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
1960
1961         /* Set the printer data */
1962         
1963         init_unistr2(&data, argv[3], UNI_STR_TERMINATE);
1964         fstrcpy(value.valuename, argv[2]);
1965         value.type = REG_SZ;
1966         value.size = data.uni_str_len * 2;
1967         value.data_p = talloc_memdup(mem_ctx, data.buffer, value.size);
1968
1969         result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
1970                 
1971         if (!W_ERROR_IS_OK(result)) {
1972                 printf ("Unable to set [%s=%s]!\n", argv[2], argv[3]);
1973                 goto done;
1974         }
1975         printf("\tSetPrinterData succeeded [%s: %s]\n", argv[2], argv[3]);
1976
1977         result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, 0, &ctr);
1978
1979         if (W_ERROR_V(result) == ERRinsufficientbuffer)
1980                 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
1981
1982         if (!W_ERROR_IS_OK(result))
1983                 goto done;
1984                 
1985         printf("%s\n", timestring(True));
1986         printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
1987
1988 done:
1989         /* cleanup */
1990         if (opened_hnd)
1991                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
1992
1993         return result;
1994 }
1995
1996 static void display_job_info_1(JOB_INFO_1 *job)
1997 {
1998         fstring username = "", document = "", text_status = "";
1999
2000         rpcstr_pull(username, job->username.buffer,
2001                     sizeof(username), -1, STR_TERMINATE);
2002
2003         rpcstr_pull(document, job->document.buffer,
2004                     sizeof(document), -1, STR_TERMINATE);
2005
2006         rpcstr_pull(text_status, job->text_status.buffer,
2007                     sizeof(text_status), -1, STR_TERMINATE);
2008
2009         printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2010                username, document, text_status, job->pagesprinted,
2011                job->totalpages);
2012 }
2013
2014 static void display_job_info_2(JOB_INFO_2 *job)
2015 {
2016         fstring username = "", document = "", text_status = "";
2017
2018         rpcstr_pull(username, job->username.buffer,
2019                     sizeof(username), -1, STR_TERMINATE);
2020
2021         rpcstr_pull(document, job->document.buffer,
2022                     sizeof(document), -1, STR_TERMINATE);
2023
2024         rpcstr_pull(text_status, job->text_status.buffer,
2025                     sizeof(text_status), -1, STR_TERMINATE);
2026
2027         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2028                username, document, text_status, job->pagesprinted,
2029                job->totalpages, job->size);
2030 }
2031
2032 /* Enumerate jobs */
2033
2034 static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli, 
2035                                       TALLOC_CTX *mem_ctx, int argc, 
2036                                       const char **argv)
2037 {
2038         WERROR result;
2039         uint32 needed, level = 1, num_jobs, i;
2040         BOOL got_hnd = False;
2041         pstring printername;
2042         fstring servername, user;
2043         POLICY_HND hnd;
2044         JOB_INFO_CTR ctr;
2045         
2046         if (argc < 2 || argc > 3) {
2047                 printf("Usage: %s printername [level]\n", argv[0]);
2048                 return WERR_OK;
2049         }
2050         
2051         if (argc == 3)
2052                 level = atoi(argv[2]);
2053
2054         /* Open printer handle */
2055
2056         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2057         strupper_m(servername);
2058         fstrcpy(user, cli->user_name);
2059         slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
2060         strupper_m(printername);
2061         pstrcat(printername, argv[1]);
2062
2063         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
2064                                              "", MAXIMUM_ALLOWED_ACCESS, 
2065                                              servername, user, &hnd);
2066
2067         if (!W_ERROR_IS_OK(result))
2068                 goto done;
2069  
2070         got_hnd = True;
2071
2072         /* Enumerate ports */
2073
2074         result = cli_spoolss_enumjobs(
2075                 cli, mem_ctx, 0, &needed, &hnd, level, 0, 1000,
2076                 &num_jobs, &ctr);
2077
2078         if (W_ERROR_V(result) == ERRinsufficientbuffer)
2079                 result = cli_spoolss_enumjobs(
2080                         cli, mem_ctx, needed, NULL, &hnd, level, 0,
2081                         1000, &num_jobs, &ctr);
2082
2083         if (!W_ERROR_IS_OK(result))
2084                 goto done;
2085
2086         for (i = 0; i < num_jobs; i++) {
2087                 switch(level) {
2088                 case 1:
2089                         display_job_info_1(&ctr.job.job_info_1[i]);
2090                         break;
2091                 case 2:
2092                         display_job_info_2(&ctr.job.job_info_2[i]);
2093                         break;
2094                 default:
2095                         d_printf("unknown info level %d\n", level);
2096                         break;
2097                 }
2098         }
2099         
2100 done:
2101         if (got_hnd)
2102                 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2103
2104         return result;
2105 }
2106
2107 /* enumerate data */
2108
2109 static WERROR cmd_spoolss_enum_data( struct cli_state *cli, 
2110                                        TALLOC_CTX *mem_ctx, int argc, 
2111                                        const char **argv)
2112 {
2113         WERROR result;
2114         uint32 i=0, val_needed, data_needed;
2115         BOOL got_hnd = False;
2116         pstring printername;
2117         fstring servername, user;
2118         POLICY_HND hnd;
2119
2120         if (argc != 2) {
2121                 printf("Usage: %s printername\n", argv[0]);
2122                 return WERR_OK;
2123         }
2124         
2125         /* Open printer handle */
2126
2127         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2128         strupper_m(servername);
2129         fstrcpy(user, cli->user_name);
2130         slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2131         strupper_m(printername);
2132         pstrcat(printername, argv[1]);
2133
2134         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
2135                                              "", MAXIMUM_ALLOWED_ACCESS, 
2136                                              servername, user, &hnd);
2137
2138         if (!W_ERROR_IS_OK(result))
2139                 goto done;
2140  
2141         got_hnd = True;
2142
2143         /* Enumerate data */
2144
2145         result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2146                                              &val_needed, &data_needed,
2147                                              NULL);
2148         while (W_ERROR_IS_OK(result)) {
2149                 REGISTRY_VALUE value;
2150                 result = cli_spoolss_enumprinterdata(
2151                         cli, mem_ctx, &hnd, i++, val_needed,
2152                         data_needed, 0, 0, &value);
2153                 if (W_ERROR_IS_OK(result))
2154                         display_reg_value(value);
2155         }
2156         if (W_ERROR_V(result) == ERRnomoreitems)
2157                 result = W_ERROR(ERRsuccess);
2158
2159 done:
2160         if (got_hnd)
2161                 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2162
2163         return result;
2164 }
2165
2166 /* enumerate data for a given key */
2167
2168 static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli, 
2169                                           TALLOC_CTX *mem_ctx, int argc, 
2170                                           const char **argv)
2171 {
2172         WERROR result;
2173         uint32 needed, i;
2174         BOOL got_hnd = False;
2175         pstring printername;
2176         fstring servername, user;
2177         const char *keyname = NULL;
2178         POLICY_HND hnd;
2179         REGVAL_CTR ctr;
2180
2181         if (argc != 3) {
2182                 printf("Usage: %s printername <keyname>\n", argv[0]);
2183                 return WERR_OK;
2184         }
2185         
2186         keyname = argv[2];
2187
2188         /* Open printer handle */
2189
2190         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2191         strupper_m(servername);
2192         fstrcpy(user, cli->user_name);
2193         slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2194         strupper_m(printername);
2195         pstrcat(printername, argv[1]);
2196
2197         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
2198                                              "", MAXIMUM_ALLOWED_ACCESS, 
2199                                              servername, user, &hnd);
2200
2201         if (!W_ERROR_IS_OK(result))
2202                 goto done;
2203  
2204         got_hnd = True;
2205
2206         /* Enumerate subkeys */
2207
2208         result = cli_spoolss_enumprinterdataex(
2209                 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL);
2210
2211         if (W_ERROR_V(result) == ERRmoredata)
2212                 result = cli_spoolss_enumprinterdataex(
2213                         cli, mem_ctx, needed, NULL, &hnd, keyname, &ctr);
2214
2215         if (!W_ERROR_IS_OK(result))
2216                 goto done;
2217
2218         for (i=0; i < ctr.num_values; i++) {
2219                 display_reg_value(*(ctr.values[i]));
2220         }
2221
2222         regval_ctr_destroy(&ctr);
2223
2224 done:
2225         if (got_hnd)
2226                 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2227
2228         return result;
2229 }
2230
2231 /* enumerate subkeys */
2232
2233 static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli, 
2234                                              TALLOC_CTX *mem_ctx, int argc, 
2235                                              const char **argv)
2236 {
2237         WERROR result;
2238         uint32 needed, returned;
2239         BOOL got_hnd = False;
2240         pstring printername;
2241         fstring servername, user;
2242         const char *keyname = NULL;
2243         POLICY_HND hnd;
2244         uint16 *keylist = NULL, *curkey;
2245
2246         if (argc < 2 || argc > 3) {
2247                 printf("Usage: %s printername [keyname]\n", argv[0]);
2248                 return WERR_OK;
2249         }
2250         
2251         if (argc == 3)
2252                 keyname = argv[2];
2253         else
2254                 keyname = "";
2255
2256         /* Open printer handle */
2257
2258         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2259         strupper_m(servername);
2260         fstrcpy(user, cli->user_name);
2261         slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2262         strupper_m(printername);
2263         pstrcat(printername, argv[1]);
2264
2265         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
2266                                              "", MAXIMUM_ALLOWED_ACCESS, 
2267                                              servername, user, &hnd);
2268
2269         if (!W_ERROR_IS_OK(result))
2270                 goto done;
2271  
2272         got_hnd = True;
2273
2274         /* Enumerate subkeys */
2275
2276         result = cli_spoolss_enumprinterkey(
2277                 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL, NULL);
2278
2279         if (W_ERROR_V(result) == ERRmoredata)
2280                 result = cli_spoolss_enumprinterkey(
2281                         cli, mem_ctx, needed, NULL, &hnd, keyname, &keylist,
2282                         &returned);
2283
2284         if (!W_ERROR_IS_OK(result))
2285                 goto done;
2286
2287         curkey = keylist;
2288         while (*curkey != 0) {
2289                 pstring subkey;
2290                 rpcstr_pull(subkey, curkey, sizeof(subkey), -1, 
2291                             STR_TERMINATE);
2292                 printf("%s\n", subkey);
2293                 curkey += strlen(subkey) + 1;
2294         }
2295
2296         safe_free(keylist);
2297
2298 done:
2299         if (got_hnd)
2300                 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2301
2302         return result;
2303 }
2304
2305 static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, 
2306                                      TALLOC_CTX *mem_ctx, int argc, 
2307                                      const char **argv)
2308 {
2309         fstring servername, printername;
2310         POLICY_HND hnd;
2311         BOOL got_hnd = False;
2312         WERROR result;
2313         SPOOL_NOTIFY_OPTION option;
2314
2315         if (argc != 2) {
2316                 printf("Usage: %s printername\n", argv[0]);
2317                 result = WERR_OK;
2318                 goto done;
2319         }
2320
2321         /* Open printer */
2322
2323         slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
2324         strupper_m(servername);
2325
2326         slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
2327                  argv[1]);
2328         strupper_m(printername);
2329
2330         result = cli_spoolss_open_printer_ex(
2331                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
2332                 servername, cli->user_name, &hnd);
2333
2334         if (!W_ERROR_IS_OK(result)) {
2335                 printf("Error opening %s\n", argv[1]);
2336                 goto done;
2337         }
2338
2339         got_hnd = True;
2340
2341         /* Create spool options */
2342
2343         ZERO_STRUCT(option);
2344
2345         option.version = 2;
2346         option.option_type_ptr = 1;
2347         option.count = option.ctr.count = 2;
2348
2349         option.ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)talloc(
2350                 mem_ctx, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * 2);
2351
2352         ZERO_STRUCT(option.ctr.type[0]);
2353         option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2354         option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2355         option.ctr.type[0].fields_ptr = 1;
2356         option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2357
2358         ZERO_STRUCT(option.ctr.type[1]);
2359         option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2360         option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2361         option.ctr.type[1].fields_ptr = 1;
2362         option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2363
2364         /* Send rffpcnex */
2365
2366         slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2367         strupper_m(servername);
2368
2369         result = cli_spoolss_rffpcnex(
2370                 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2371
2372         if (!W_ERROR_IS_OK(result)) {
2373                 printf("Error rffpcnex %s\n", argv[1]);
2374                 goto done;
2375         }
2376
2377 done:           
2378         if (got_hnd)
2379                 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2380
2381         return result;
2382 }
2383
2384 /* List of commands exported by this module */
2385 struct cmd_set spoolss_commands[] = {
2386
2387         { "SPOOLSS"  },
2388
2389         { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   PI_SPOOLSS, "Add a print driver",                  "" },
2390         { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       PI_SPOOLSS, "Add a printer",                       "" },
2391         { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       PI_SPOOLSS, "Delete a printer driver",             "" },
2392         { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          PI_SPOOLSS, "Enumerate printer data",              "" },
2393         { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       PI_SPOOLSS, "Enumerate printer data for a key",    "" },
2394         { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    PI_SPOOLSS, "Enumerate printer keys",              "" },
2395         { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          PI_SPOOLSS, "Enumerate print jobs",                "" },
2396         { "enumports",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         PI_SPOOLSS, "Enumerate printer ports",             "" },
2397         { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       PI_SPOOLSS, "Enumerate installed printer drivers", "" },
2398         { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      PI_SPOOLSS, "Enumerate printers",                  "" },
2399         { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     PI_SPOOLSS, "Get print driver data",               "" },
2400         { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   PI_SPOOLSS, "Get printer driver data with keyname", ""},
2401         { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          PI_SPOOLSS, "Get print driver information",        "" },
2402         { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       PI_SPOOLSS, "Get print driver upload directory",   "" },
2403         { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         PI_SPOOLSS, "Get printer info",                    "" },
2404         { "getprintprocdir",RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    PI_SPOOLSS, "Get print processor directory",       "" },
2405         { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    PI_SPOOLSS, "Open printer handle",                 "" },
2406         { "setdriver",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          PI_SPOOLSS, "Set printer driver",                  "" },
2407         { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    PI_SPOOLSS, "Get print processor directory",       "" },
2408         { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            PI_SPOOLSS, "Add form",                            "" },
2409         { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            PI_SPOOLSS, "Set form",                            "" },
2410         { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            PI_SPOOLSS, "Get form",                            "" },
2411         { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         PI_SPOOLSS, "Delete form",                         "" },
2412         { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         PI_SPOOLSS, "Enumerate forms",                     "" },
2413         { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         PI_SPOOLSS, "Set printer comment",                 "" },
2414         { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,         PI_SPOOLSS, "Set printername",                 "" },
2415         { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     PI_SPOOLSS, "Set REG_SZ printer data",             "" },
2416         { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           PI_SPOOLSS, "Rffpcnex test", "" },
2417
2418         { NULL }
2419 };