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