Removed version number from file header.
[vlendec/samba-autobuild/.git] / source3 / rpcclient / cmd_spoolss.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Gerald Carter                     2001
6    Copyright (C) Tim Potter                        2000
7    Copyright (C) Andrew Tridgell              1992-1999
8    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9  
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "rpcclient.h"
27
28 struct table_node {
29         char    *long_archi;
30         char    *short_archi;
31         int     version;
32 };
33  
34 struct table_node archi_table[]= {
35
36         {"Windows 4.0",          "WIN40",       0 },
37         {"Windows NT x86",       "W32X86",      2 },
38         {"Windows NT R4000",     "W32MIPS",     2 },
39         {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
40         {"Windows NT PowerPC",   "W32PPC",      2 },
41         {NULL,                   "",            -1 }
42 };
43
44 /****************************************************************************
45 function to do the mapping between the long architecture name and
46 the short one.
47 ****************************************************************************/
48 BOOL get_short_archi(char *short_archi, char *long_archi)
49 {
50         int i=-1;
51
52         DEBUG(107,("Getting architecture dependant directory\n"));
53         do {
54                 i++;
55         } while ( (archi_table[i].long_archi!=NULL ) &&
56                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
57
58         if (archi_table[i].long_archi==NULL) {
59                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
60                 return False;
61         }
62
63         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
64
65         DEBUGADD(108,("index: [%d]\n", i));
66         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
67         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
68
69         return True;
70 }
71
72
73 /**********************************************************************
74  * dummy function  -- placeholder
75   */
76 static NTSTATUS cmd_spoolss_not_implemented(struct cli_state *cli, 
77                                             TALLOC_CTX *mem_ctx,
78                                             int argc, char **argv)
79 {
80         printf ("(*) This command is not currently implemented.\n");
81         return NT_STATUS_OK;
82 }
83
84 /***********************************************************************
85  * Get printer information
86  */
87 static NTSTATUS cmd_spoolss_open_printer_ex(struct cli_state *cli, 
88                                             TALLOC_CTX *mem_ctx,
89                                             int argc, char **argv)
90 {
91         WERROR          werror;
92         pstring         printername;
93         fstring         servername, user;
94         POLICY_HND      hnd;
95         
96         if (argc != 2) {
97                 printf("Usage: %s <printername>\n", argv[0]);
98                 return NT_STATUS_OK;
99         }
100         
101         if (!cli)
102                 return NT_STATUS_UNSUCCESSFUL;
103
104         slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
105         strupper (servername);
106         fstrcpy  (user, cli->user_name);
107         fstrcpy  (printername, argv[1]);
108
109         /* Open the printer handle */
110
111         werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
112                                              "", MAXIMUM_ALLOWED_ACCESS, 
113                                              servername, user, &hnd);
114
115         if (W_ERROR_IS_OK(werror)) {
116                 printf("Printer %s opened successfully\n", printername);
117                 werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
118
119                 if (!W_ERROR_IS_OK(werror)) {
120                         printf("Error closing printer handle! (%s)\n", 
121                                 get_dos_error_msg(werror));
122                 }
123         }
124
125         return werror_to_ntstatus(werror);
126 }
127
128
129 /****************************************************************************
130 printer info level 0 display function
131 ****************************************************************************/
132 static void display_print_info_0(PRINTER_INFO_0 *i0)
133 {
134         fstring         name = "";
135         fstring         servername = "";
136
137         if (i0->printername.buffer)
138                 rpcstr_pull(name, i0->printername.buffer, sizeof(name), 0, STR_TERMINATE);
139
140         if (i0->servername.buffer)
141                 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), 0,STR_TERMINATE);
142   
143         printf("\tprintername:[%s]\n", name);
144         printf("\tservername:[%s]\n", servername);
145         printf("\tcjobs:[0x%x]\n", i0->cjobs);
146         printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
147         
148         printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month, 
149                i0->day, i0->dayofweek);
150         printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute, 
151                i0->second, i0->milliseconds);
152         
153         printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
154         printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
155         
156         printf("\tmajorversion:[0x%x]\n", i0->major_version);
157         printf("\tbuildversion:[0x%x]\n", i0->build_version);
158         
159         printf("\tunknown7:[0x%x]\n", i0->unknown7);
160         printf("\tunknown8:[0x%x]\n", i0->unknown8);
161         printf("\tunknown9:[0x%x]\n", i0->unknown9);
162         printf("\tsession_counter:[0x%x]\n", i0->session_counter);
163         printf("\tunknown11:[0x%x]\n", i0->unknown11);
164         printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
165         printf("\tunknown13:[0x%x]\n", i0->unknown13);
166         printf("\tunknown14:[0x%x]\n", i0->unknown14);
167         printf("\tunknown15:[0x%x]\n", i0->unknown15);
168         printf("\tunknown16:[0x%x]\n", i0->unknown16);
169         printf("\tchange_id:[0x%x]\n", i0->change_id);
170         printf("\tunknown18:[0x%x]\n", i0->unknown18);
171         printf("\tstatus:[0x%x]\n", i0->status);
172         printf("\tunknown20:[0x%x]\n", i0->unknown20);
173         printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
174         printf("\tunknown22:[0x%x]\n", i0->unknown22);
175         printf("\tunknown23:[0x%x]\n", i0->unknown23);
176         printf("\tunknown24:[0x%x]\n", i0->unknown24);
177         printf("\tunknown25:[0x%x]\n", i0->unknown25);
178         printf("\tunknown26:[0x%x]\n", i0->unknown26);
179         printf("\tunknown27:[0x%x]\n", i0->unknown27);
180         printf("\tunknown28:[0x%x]\n", i0->unknown28);
181         printf("\tunknown29:[0x%x]\n", i0->unknown29);
182 }
183
184 /****************************************************************************
185 printer info level 1 display function
186 ****************************************************************************/
187 static void display_print_info_1(PRINTER_INFO_1 *i1)
188 {
189         fstring desc = "";
190         fstring name = "";
191         fstring comm = "";
192
193         if (i1->description.buffer)
194                 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), 0, 
195                             STR_TERMINATE);
196
197         if (i1->name.buffer)
198                 rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, 
199                             STR_TERMINATE);
200
201         if (i1->comment.buffer)
202                 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), 0, 
203                             STR_TERMINATE);
204
205         printf("\tflags:[0x%x]\n", i1->flags);
206         printf("\tname:[%s]\n", name);
207         printf("\tdescription:[%s]\n", desc);
208         printf("\tcomment:[%s]\n\n", comm);
209 }
210
211 /****************************************************************************
212 printer info level 2 display function
213 ****************************************************************************/
214 static void display_print_info_2(PRINTER_INFO_2 *i2)
215 {
216         fstring servername = "";
217         fstring printername = "";
218         fstring sharename = "";
219         fstring portname = "";
220         fstring drivername = "";
221         fstring comment = "";
222         fstring location = "";
223         fstring sepfile = "";
224         fstring printprocessor = "";
225         fstring datatype = "";
226         fstring parameters = "";
227         
228         if (i2->servername.buffer)
229                 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), 0, STR_TERMINATE);
230
231         if (i2->printername.buffer)
232                 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), 0, STR_TERMINATE);
233
234         if (i2->sharename.buffer)
235                 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), 0, STR_TERMINATE);
236
237         if (i2->portname.buffer)
238                 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), 0, STR_TERMINATE);
239
240         if (i2->drivername.buffer)
241                 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), 0, STR_TERMINATE);
242
243         if (i2->comment.buffer)
244                 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), 0, STR_TERMINATE);
245
246         if (i2->location.buffer)
247                 rpcstr_pull(location, i2->location.buffer,sizeof(location), 0, STR_TERMINATE);
248
249         if (i2->sepfile.buffer)
250                 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), 0, STR_TERMINATE);
251
252         if (i2->printprocessor.buffer) 
253                 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), 0, STR_TERMINATE);
254
255         if (i2->datatype.buffer)
256                 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), 0, STR_TERMINATE);
257
258         if (i2->parameters.buffer)
259                 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), 0, STR_TERMINATE);
260
261         printf("\tservername:[%s]\n", servername);
262         printf("\tprintername:[%s]\n", printername);
263         printf("\tsharename:[%s]\n", sharename);
264         printf("\tportname:[%s]\n", portname);
265         printf("\tdrivername:[%s]\n", drivername);
266         printf("\tcomment:[%s]\n", comment);
267         printf("\tlocation:[%s]\n", location);
268         printf("\tsepfile:[%s]\n", sepfile);
269         printf("\tprintprocessor:[%s]\n", printprocessor);
270         printf("\tdatatype:[%s]\n", datatype);
271         printf("\tparameters:[%s]\n", parameters);
272         printf("\tattributes:[0x%x]\n", i2->attributes);
273         printf("\tpriority:[0x%x]\n", i2->priority);
274         printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
275         printf("\tstarttime:[0x%x]\n", i2->starttime);
276         printf("\tuntiltime:[0x%x]\n", i2->untiltime);
277         printf("\tstatus:[0x%x]\n", i2->status);
278         printf("\tcjobs:[0x%x]\n", i2->cjobs);
279         printf("\taverageppm:[0x%x]\n", i2->averageppm);
280
281         if (i2->secdesc) display_sec_desc(i2->secdesc);
282 }
283
284 /****************************************************************************
285 printer info level 3 display function
286 ****************************************************************************/
287 static void display_print_info_3(PRINTER_INFO_3 *i3)
288 {
289         printf("\tflags:[0x%x]\n", i3->flags);
290
291         display_sec_desc(i3->secdesc);
292 }
293
294 /* Enumerate printers */
295
296 static NTSTATUS cmd_spoolss_enum_printers(struct cli_state *cli, 
297                                           TALLOC_CTX *mem_ctx,
298                                           int argc, char **argv)
299 {
300         WERROR                  result;
301         uint32                  info_level = 1;
302         PRINTER_INFO_CTR        ctr;
303         uint32                  i = 0, num_printers, needed;
304
305         if (argc > 2) 
306         {
307                 printf("Usage: %s [level]\n", argv[0]);
308                 return NT_STATUS_OK;
309         }
310
311         if (argc == 2) {
312                 info_level = atoi(argv[1]);
313         }
314
315         /* Enumerate printers  -- Should we enumerate types other 
316            than PRINTER_ENUM_LOCAL?  Maybe accept as a parameter?  --jerry */
317
318         ZERO_STRUCT(ctr);
319
320         result = cli_spoolss_enum_printers(
321                 cli, mem_ctx, 0, &needed, PRINTER_ENUM_LOCAL, 
322                 info_level, &num_printers, &ctr);
323
324         if (W_ERROR_V(result) == ERRinsufficientbuffer)
325                 result = cli_spoolss_enum_printers(
326                         cli, mem_ctx, needed, NULL, PRINTER_ENUM_LOCAL, 
327                         info_level, &num_printers, &ctr);
328
329         if (W_ERROR_IS_OK(result)) {
330                 if (!num_printers)
331                         printf ("No Printers printers returned.\n");
332         
333                 switch(info_level) {
334                 case 0:
335                         for (i=0; i < num_printers; i++)
336                                 display_print_info_0(&ctr.printers_0[i]);
337                         break;
338                 case 1:
339                         for (i=0; i < num_printers; i++)
340                                 display_print_info_1(&ctr.printers_1[i]);
341                         break;
342                 case 2:
343                         for (i=0; i < num_printers; i++)
344                                 display_print_info_2(&ctr.printers_2[i]);
345                         break;
346                 case 3:
347                         for (i=0; i < num_printers; i++)
348                                 display_print_info_3(&ctr.printers_3[i]);
349                         break;
350                 default:
351                         printf("unknown info level %d\n", info_level);
352                         break;
353                 }
354         }
355
356         return werror_to_ntstatus(result);
357 }
358
359 /****************************************************************************
360 port info level 1 display function
361 ****************************************************************************/
362 static void display_port_info_1(PORT_INFO_1 *i1)
363 {
364         fstring buffer;
365         
366         rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), 0, STR_TERMINATE);
367         printf("\tPort Name:\t[%s]\n", buffer);
368 }
369
370 /****************************************************************************
371 port info level 2 display function
372 ****************************************************************************/
373 static void display_port_info_2(PORT_INFO_2 *i2)
374 {
375         fstring buffer;
376         
377         rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), 0, STR_TERMINATE);
378         printf("\tPort Name:\t[%s]\n", buffer);
379         rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), 0, STR_TERMINATE);
380
381         printf("\tMonitor Name:\t[%s]\n", buffer);
382         rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), 0, STR_TERMINATE);
383
384         printf("\tDescription:\t[%s]\n", buffer);
385         printf("\tPort Type:\t[%d]\n", i2->port_type);
386         printf("\tReserved:\t[%d]\n", i2->reserved);
387         printf("\n");
388 }
389
390 /* Enumerate ports */
391
392 static NTSTATUS cmd_spoolss_enum_ports(struct cli_state *cli, 
393                                        TALLOC_CTX *mem_ctx, int argc, 
394                                        char **argv)
395 {
396         WERROR                  result;
397         uint32                  needed, info_level = 1;
398         PORT_INFO_CTR           ctr;
399         int                     returned;
400         
401         if (argc > 2) {
402                 printf("Usage: %s [level]\n", argv[0]);
403                 return NT_STATUS_OK;
404         }
405         
406         if (argc == 2)
407                 info_level = atoi(argv[1]);
408
409         /* Enumerate ports */
410
411         ZERO_STRUCT(ctr);
412
413         result = cli_spoolss_enum_ports(cli, mem_ctx, 0, &needed, info_level, 
414                                         &returned, &ctr);
415
416         if (W_ERROR_V(result) == ERRinsufficientbuffer)
417                 result = cli_spoolss_enum_ports(cli, mem_ctx, needed, NULL,
418                                                 info_level, &returned, &ctr);
419
420         if (W_ERROR_IS_OK(result)) {
421                 int i;
422
423                 for (i = 0; i < returned; i++) {
424                         switch (info_level) {
425                         case 1:
426                                 display_port_info_1(&ctr.port.info_1[i]);
427                                 break;
428                         case 2:
429                                 display_port_info_2(&ctr.port.info_2[i]);
430                                 break;
431                         default:
432                                 printf("unknown info level %d\n", info_level);
433                                 break;
434                         }
435                 }
436         }
437         
438         return werror_to_ntstatus(result);
439 }
440
441 /***********************************************************************
442  * Get printer information
443  */
444 static NTSTATUS cmd_spoolss_getprinter(struct cli_state *cli, 
445                                        TALLOC_CTX *mem_ctx,
446                                        int argc, char **argv)
447 {
448         POLICY_HND      pol;
449         WERROR          werror;
450         NTSTATUS        result;
451         uint32          info_level = 1;
452         BOOL            opened_hnd = False;
453         PRINTER_INFO_CTR ctr;
454         fstring         printername, 
455                         servername,
456                         user;
457
458         if (argc == 1 || argc > 3) {
459                 printf("Usage: %s <printername> [level]\n", argv[0]);
460                 return NT_STATUS_OK;
461         }
462
463         /* Open a printer handle */
464         if (argc == 3) {
465                 info_level = atoi(argv[2]);
466         }
467
468         slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
469         strupper (servername);
470         slprintf (printername, sizeof(fstring)-1, "%s\\%s", servername, argv[1]);
471         fstrcpy  (user, cli->user_name);
472         
473         /* get a printer handle */
474
475         werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
476                                              "", MAXIMUM_ALLOWED_ACCESS, 
477                                              servername, user, &pol);
478
479         result = werror_to_ntstatus(werror);
480
481         if (!NT_STATUS_IS_OK(result))
482                 goto done;
483  
484         opened_hnd = True;
485
486         /* Get printer info */
487
488         result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
489
490         if (!NT_STATUS_IS_OK(result))
491                 goto done;
492
493         /* Display printer info */
494
495         switch (info_level) {
496         case 0: 
497                 display_print_info_0(ctr.printers_0);
498                 break;
499         case 1:
500                 display_print_info_1(ctr.printers_1);
501                 break;
502         case 2:
503                 display_print_info_2(ctr.printers_2);
504                 break;
505         case 3:
506                 display_print_info_3(ctr.printers_3);
507                 break;
508         default:
509                 printf("unknown info level %d\n", info_level);
510                 break;
511         }
512
513  done: 
514         if (opened_hnd) 
515                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
516
517         return result;
518 }
519
520 /****************************************************************************
521 printer info level 0 display function
522 ****************************************************************************/
523 static void display_print_driver_1(DRIVER_INFO_1 *i1)
524 {
525         fstring name;
526         if (i1 == NULL)
527                 return;
528
529         rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, STR_TERMINATE);
530
531         printf ("Printer Driver Info 1:\n");
532         printf ("\tDriver Name: [%s]\n\n", name);
533         
534         return;
535 }
536
537 /****************************************************************************
538 printer info level 1 display function
539 ****************************************************************************/
540 static void display_print_driver_2(DRIVER_INFO_2 *i1)
541 {
542         fstring name;
543         fstring architecture;
544         fstring driverpath;
545         fstring datafile;
546         fstring configfile;
547         if (i1 == NULL)
548                 return;
549
550         rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, STR_TERMINATE);
551         rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), 0, STR_TERMINATE);
552         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), 0, STR_TERMINATE);
553         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), 0, STR_TERMINATE);
554         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), 0, STR_TERMINATE);
555
556         printf ("Printer Driver Info 2:\n");
557         printf ("\tVersion: [%x]\n", i1->version);
558         printf ("\tDriver Name: [%s]\n", name);
559         printf ("\tArchitecture: [%s]\n", architecture);
560         printf ("\tDriver Path: [%s]\n", driverpath);
561         printf ("\tDatafile: [%s]\n", datafile);
562         printf ("\tConfigfile: [%s]\n\n", configfile);
563
564         return;
565 }
566
567 /****************************************************************************
568 printer info level 2 display function
569 ****************************************************************************/
570 static void display_print_driver_3(DRIVER_INFO_3 *i1)
571 {
572         fstring name;
573         fstring architecture;
574         fstring driverpath;
575         fstring datafile;
576         fstring configfile;
577         fstring helpfile;
578         fstring dependentfiles;
579         fstring monitorname;
580         fstring defaultdatatype;
581         
582         int length=0;
583         BOOL valid = True;
584         
585         if (i1 == NULL)
586                 return;
587
588         rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, STR_TERMINATE);
589         rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), 0, STR_TERMINATE);
590         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), 0, STR_TERMINATE);
591         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), 0, STR_TERMINATE);
592         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), 0, STR_TERMINATE);
593         rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), 0, STR_TERMINATE);
594         rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), 0, STR_TERMINATE);
595         rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), 0, STR_TERMINATE);
596
597         printf ("Printer Driver Info 3:\n");
598         printf ("\tVersion: [%x]\n", i1->version);
599         printf ("\tDriver Name: [%s]\n",name);
600         printf ("\tArchitecture: [%s]\n", architecture);
601         printf ("\tDriver Path: [%s]\n", driverpath);
602         printf ("\tDatafile: [%s]\n", datafile);
603         printf ("\tConfigfile: [%s]\n", configfile);
604         printf ("\tHelpfile: [%s]\n\n", helpfile);
605
606         while (valid)
607         {
608                 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), 0, STR_TERMINATE);
609                 
610                 length+=strlen(dependentfiles)+1;
611                 
612                 if (strlen(dependentfiles) > 0)
613                 {
614                         printf ("\tDependentfiles: [%s]\n", dependentfiles);
615                 }
616                 else
617                 {
618                         valid = False;
619                 }
620         }
621         
622         printf ("\n");
623
624         printf ("\tMonitorname: [%s]\n", monitorname);
625         printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
626
627         return; 
628 }
629
630 /***********************************************************************
631  * Get printer information
632  */
633 static NTSTATUS cmd_spoolss_getdriver(struct cli_state *cli, 
634                                       TALLOC_CTX *mem_ctx,
635                                       int argc, char **argv)
636 {
637         POLICY_HND      pol;
638         WERROR          werror;
639         NTSTATUS        result;
640         uint32          info_level = 3;
641         BOOL            opened_hnd = False;
642         PRINTER_DRIVER_CTR      ctr;
643         fstring         printername, 
644                         servername, 
645                         user;
646         uint32          i;
647
648         if ((argc == 1) || (argc > 3)) 
649         {
650                 printf("Usage: %s <printername> [level]\n", argv[0]);
651                 return NT_STATUS_OK;
652         }
653
654         /* get the arguments need to open the printer handle */
655         slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
656         strupper (servername);
657         fstrcpy  (user, cli->user_name);
658         fstrcpy  (printername, argv[1]);
659         if (argc == 3)
660                 info_level = atoi(argv[2]);
661
662         /* Open a printer handle */
663
664         werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
665                                              PRINTER_ACCESS_USE,
666                                              servername, user, &pol);
667
668         result = werror_to_ntstatus(werror);
669
670         if (!NT_STATUS_IS_OK(result)) {
671                 printf("Error opening printer handle for %s!\n", printername);
672                 return result;
673         }
674
675         opened_hnd = True;
676
677         /* loop through and print driver info level for each architecture */
678
679         for (i=0; archi_table[i].long_archi!=NULL; i++) {
680                 uint32 needed;
681
682                 werror = cli_spoolss_getprinterdriver(
683                         cli, mem_ctx, 0, &needed, &pol, info_level, 
684                         archi_table[i].long_archi, &ctr);
685
686                 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
687                         werror = cli_spoolss_getprinterdriver(
688                                 cli, mem_ctx, needed, NULL, &pol, info_level, 
689                                 archi_table[i].long_archi, &ctr);
690
691                 if (!W_ERROR_IS_OK(werror))
692                         continue;
693                         
694                 printf ("\n[%s]\n", archi_table[i].long_archi);
695
696                 switch (info_level) {
697                 case 1:
698                         display_print_driver_1 (ctr.info1);
699                         break;
700                 case 2:
701                         display_print_driver_2 (ctr.info2);
702                         break;
703                 case 3:
704                         display_print_driver_3 (ctr.info3);
705                         break;
706                 default:
707                         printf("unknown info level %d\n", info_level);
708                         break;
709                 }
710         }
711         
712         /* Cleanup */
713
714         if (opened_hnd)
715                 cli_spoolss_close_printer (cli, mem_ctx, &pol);
716         
717         return result;
718 }
719
720 /***********************************************************************
721  * Get printer information
722  */
723 static NTSTATUS cmd_spoolss_enum_drivers(struct cli_state *cli, 
724                                          TALLOC_CTX *mem_ctx,
725                                          int argc, char **argv)
726 {
727         NTSTATUS        result = NT_STATUS_OK;
728         uint32          info_level = 1;
729         PRINTER_DRIVER_CTR      ctr;
730         fstring         servername;
731         uint32          i, j,
732                         returned;
733
734         if (argc > 2) 
735         {
736                 printf("Usage: enumdrivers [level]\n");
737                 return NT_STATUS_OK;
738         }
739
740         /* get the arguments need to open the printer handle */
741         slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
742         strupper (servername);
743         if (argc == 2)
744                 info_level = atoi(argv[1]);
745
746
747         /* loop through and print driver info level for each architecture */
748         for (i=0; archi_table[i].long_archi!=NULL; i++) 
749         {
750                 returned = 0;   
751                 result = cli_spoolss_enumprinterdrivers (cli, mem_ctx, info_level, 
752                                 archi_table[i].long_archi, &returned, &ctr);
753
754                 if (returned == 0)
755                         continue;
756                         
757
758                 if (!NT_STATUS_IS_OK(result))
759                 {
760                         printf ("Error getting driver for environment [%s] - %s\n",
761                                 archi_table[i].long_archi, get_nt_error_msg(result));
762                         continue;
763                 }
764                 
765                 printf ("\n[%s]\n", archi_table[i].long_archi);
766                 switch (info_level) 
767                 {
768                         
769                 case 1:
770                         for (j=0; j < returned; j++) {
771                                 display_print_driver_1 (&(ctr.info1[j]));
772                         }
773                         break;
774                 case 2:
775                         for (j=0; j < returned; j++) {
776                                 display_print_driver_2 (&(ctr.info2[j]));
777                         }
778                         break;
779                 case 3:
780                         for (j=0; j < returned; j++) {
781                                 display_print_driver_3 (&(ctr.info3[j]));
782                         }
783                         break;
784                 default:
785                         printf("unknown info level %d\n", info_level);
786                         break;
787                 }
788         }
789         
790         return result;
791 }
792
793 /****************************************************************************
794 printer info level 1 display function
795 ****************************************************************************/
796 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
797 {
798         fstring name;
799         if (i1 == NULL)
800                 return;
801  
802         rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, STR_TERMINATE);
803  
804         printf ("\tDirectory Name:[%s]\n", name);
805 }
806
807 /***********************************************************************
808  * Get printer driver directory information
809  */
810 static NTSTATUS cmd_spoolss_getdriverdir(struct cli_state *cli, 
811                                          TALLOC_CTX *mem_ctx,
812                                          int argc, char **argv)
813 {
814         NTSTATUS                result;
815         fstring                 env;
816         DRIVER_DIRECTORY_CTR    ctr;
817
818         if (argc > 2) 
819         {
820                 printf("Usage: %s [environment]\n", argv[0]);
821                 return NT_STATUS_OK;
822         }
823
824         /* get the arguments need to open the printer handle */
825         if (argc == 2)
826                 fstrcpy (env, argv[1]);
827         else
828                 fstrcpy (env, "Windows NT x86");
829
830         /* Get the directory.  Only use Info level 1 */
831         result = cli_spoolss_getprinterdriverdir (cli, mem_ctx, 1, env, &ctr);
832         if (!NT_STATUS_IS_OK(result)) {
833                 return result;
834         }
835
836         
837         display_printdriverdir_1 (ctr.info1);
838
839         return result;
840 }
841
842 /*******************************************************************************
843  set the version and environment fields of a DRIVER_INFO_3 struct
844  ******************************************************************************/
845 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
846 {
847
848         int i;
849         
850         for (i=0; archi_table[i].long_archi != NULL; i++) 
851         {
852                 if (strcmp(arch, archi_table[i].short_archi) == 0)
853                 {
854                         info->version = archi_table[i].version;
855                         init_unistr (&info->architecture, archi_table[i].long_archi);
856                         break;
857                 }
858         }
859         
860         if (archi_table[i].long_archi == NULL)
861         {
862                 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
863         }
864         
865         return;
866 }
867
868
869 /**************************************************************************
870  wrapper for strtok to get the next parameter from a delimited list.
871  Needed to handle the empty parameter string denoted by "NULL"
872  *************************************************************************/
873 static char* get_driver_3_param (char* str, char* delim, UNISTR* dest)
874 {
875         char    *ptr;
876
877         /* get the next token */
878         ptr = strtok(str, delim);
879
880         /* a string of 'NULL' is used to represent an empty
881            parameter because two consecutive delimiters
882            will not return an empty string.  See man strtok(3)
883            for details */
884         if (StrCaseCmp(ptr, "NULL") == 0)
885                 ptr = NULL;
886
887         if (dest != NULL)
888                 init_unistr(dest, ptr); 
889
890         return ptr;
891 }
892
893 /********************************************************************************
894  fill in the members of a DRIVER_INFO_3 struct using a character 
895  string in the form of
896          <Long Printer Name>:<Driver File Name>:<Data File Name>:\
897              <Config File Name>:<Help File Name>:<Language Monitor Name>:\
898              <Default Data Type>:<Comma Separated list of Files> 
899  *******************************************************************************/
900 static BOOL init_drv_info_3_members (
901         TALLOC_CTX *mem_ctx, 
902         DRIVER_INFO_3 *info, 
903         char *args
904 )
905 {
906         char    *str, *str2;
907         uint32  len, i;
908         
909         /* fill in the UNISTR fields */
910         str = get_driver_3_param (args, ":", &info->name);
911         str = get_driver_3_param (NULL, ":", &info->driverpath);
912         str = get_driver_3_param (NULL, ":", &info->datafile);
913         str = get_driver_3_param (NULL, ":", &info->configfile);
914         str = get_driver_3_param (NULL, ":", &info->helpfile);
915         str = get_driver_3_param (NULL, ":", &info->monitorname);
916         str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
917
918         /* <Comma Separated List of Dependent Files> */
919         str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
920         str = str2;                     
921
922         /* begin to strip out each filename */
923         str = strtok(str, ",");         
924         len = 0;
925         while (str != NULL)
926         {
927                 /* keep a cumlative count of the str lengths */
928                 len += strlen(str)+1;
929                 str = strtok(NULL, ",");
930         }
931
932         /* allocate the space; add one extra slot for a terminating NULL.
933            Each filename is NULL terminated and the end contains a double
934            NULL */
935         if ((info->dependentfiles=(uint16*)talloc(mem_ctx, (len+1)*sizeof(uint16))) == NULL)
936         {
937                 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
938                 return False;
939         }
940         for (i=0; i<len; i++)
941         {
942                 info->dependentfiles[i] = SSVAL(&info->dependentfiles[i], 0, str2[i]);
943         }
944         info->dependentfiles[len] = '\0';
945
946         return True;
947 }
948
949
950 static NTSTATUS cmd_spoolss_addprinterdriver(struct cli_state *cli, 
951                                              TALLOC_CTX *mem_ctx,
952                                              int argc, char **argv)
953 {
954         NTSTATUS                result;
955         uint32                  level = 3;
956         PRINTER_DRIVER_CTR      ctr;
957         DRIVER_INFO_3           info3;
958         fstring                 arch;
959         fstring                 driver_name;
960
961         /* parse the command arguements */
962         if (argc != 3)
963         {
964                 printf ("Usage: %s <Environment>\\\n", argv[0]);
965                 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
966                 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
967                 printf ("\t<Default Data Type>:<Comma Separated list of Files>\n");
968
969                 return NT_STATUS_OK;
970         }
971                 
972         /* Fill in the DRIVER_INFO_3 struct */
973         ZERO_STRUCT(info3);
974         if (!get_short_archi(arch, argv[1]))
975         {
976                 printf ("Error Unknown architechture [%s]\n", argv[1]);
977                 return NT_STATUS_INVALID_PARAMETER;
978         }
979         else
980                 set_drv_info_3_env(&info3, arch);
981
982         if (!init_drv_info_3_members(mem_ctx, &info3, argv[2]))
983         {
984                 printf ("Error Invalid parameter list - %s.\n", argv[2]);
985                 return NT_STATUS_INVALID_PARAMETER;
986         }
987
988
989         ctr.info3 = &info3;
990         result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
991         if (!NT_STATUS_IS_OK(result)) {
992                 return result;
993         }
994
995         rpcstr_pull(driver_name, info3.name.buffer, sizeof(driver_name), 0, STR_TERMINATE);
996         printf ("Printer Driver %s successfully installed.\n", driver_name);
997
998         return result;
999 }
1000
1001
1002 static NTSTATUS cmd_spoolss_addprinterex(struct cli_state *cli, 
1003                                          TALLOC_CTX *mem_ctx, 
1004                                          int argc, char **argv)
1005 {
1006         NTSTATUS                result;
1007         uint32                  level = 2;
1008         PRINTER_INFO_CTR        ctr;
1009         PRINTER_INFO_2          info2;
1010         fstring                 servername;
1011         
1012         /* parse the command arguements */
1013         if (argc != 5)
1014         {
1015                 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1016                 return NT_STATUS_OK;
1017         }
1018         
1019         slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1020         strupper (servername);
1021
1022         /* Fill in the DRIVER_INFO_3 struct */
1023         ZERO_STRUCT(info2);
1024 #if 0   /* JERRY */
1025         init_unistr( &info2.servername,         servername);
1026 #endif
1027         init_unistr( &info2.printername,        argv[1]);
1028         init_unistr( &info2.sharename,          argv[2]);
1029         init_unistr( &info2.drivername,         argv[3]);
1030         init_unistr( &info2.portname,           argv[4]);
1031         init_unistr( &info2.comment,            "Created by rpcclient");
1032         init_unistr( &info2.printprocessor,     "winprint");
1033         init_unistr( &info2.datatype,           "RAW");
1034         info2.devmode =         NULL;
1035         info2.secdesc =         NULL;
1036         info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
1037         info2.priority          = 0;
1038         info2.defaultpriority   = 0;
1039         info2.starttime         = 0;
1040         info2.untiltime         = 0;
1041         
1042         /* These three fields must not be used by AddPrinter() 
1043            as defined in the MS Platform SDK documentation..  
1044            --jerry
1045         info2.status            = 0;
1046         info2.cjobs             = 0;
1047         info2.averageppm        = 0;
1048         */
1049
1050         ctr.printers_2 = &info2;
1051         result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1052         if (!NT_STATUS_IS_OK(result)) {
1053                 return result;
1054         }
1055
1056         printf ("Printer %s successfully installed.\n", argv[1]);
1057
1058         return result;
1059 }
1060
1061 static NTSTATUS cmd_spoolss_setdriver(struct cli_state *cli, 
1062                                       TALLOC_CTX *mem_ctx,
1063                                       int argc, char **argv)
1064 {
1065         POLICY_HND              pol;
1066         WERROR                  result;
1067         NTSTATUS                nt_status;
1068         uint32                  level = 2;
1069         BOOL                    opened_hnd = False;
1070         PRINTER_INFO_CTR        ctr;
1071         PRINTER_INFO_2          info2;
1072         fstring                 servername,
1073                                 printername,
1074                                 user;
1075         
1076         /* parse the command arguements */
1077         if (argc != 3)
1078         {
1079                 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1080                 return NT_STATUS_OK;
1081         }
1082
1083         slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1084         strupper (servername);
1085         slprintf (printername, sizeof(fstring)-1, "%s\\%s", servername, argv[1]);
1086         fstrcpy  (user, cli->user_name);
1087
1088         /* Get a printer handle */
1089
1090         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
1091                                              MAXIMUM_ALLOWED_ACCESS, 
1092                                              servername, user, &pol);
1093
1094         nt_status = werror_to_ntstatus(result);
1095
1096         if (!NT_STATUS_IS_OK(nt_status))
1097                 goto done;
1098  
1099         opened_hnd = True;
1100
1101         /* Get printer info */
1102
1103         ZERO_STRUCT (info2);
1104         ctr.printers_2 = &info2;
1105
1106         nt_status = cli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1107
1108         if (!NT_STATUS_IS_OK(nt_status)) {
1109                 printf ("Unable to retrieve printer information!\n");
1110                 goto done;
1111         }
1112
1113         /* Set the printer driver */
1114
1115         init_unistr(&ctr.printers_2->drivername, argv[2]);
1116
1117         nt_status = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1118
1119         if (!NT_STATUS_IS_OK(nt_status)) {
1120                 printf("SetPrinter call failed!\n");
1121                 goto done;;
1122         }
1123
1124         printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1125
1126 done:
1127         /* Cleanup */
1128
1129         if (opened_hnd)
1130                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
1131         
1132         return nt_status;               
1133 }
1134
1135
1136 static NTSTATUS cmd_spoolss_deletedriver(struct cli_state *cli, 
1137                                          TALLOC_CTX *mem_ctx,
1138                                          int argc, char **argv)
1139 {
1140         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
1141         fstring                 servername;
1142         int                     i;
1143         
1144         /* parse the command arguements */
1145         if (argc != 2)
1146         {
1147                 printf ("Usage: %s <driver>\n", argv[0]);
1148                 return NT_STATUS_OK;
1149         }
1150
1151         slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1152         strupper (servername);
1153
1154         /* delete the driver for all architectures */
1155         for (i=0; archi_table[i].long_archi; i++)
1156         {
1157                 /* make the call to remove the driver */
1158                 result = cli_spoolss_deleteprinterdriver(cli, mem_ctx, 
1159                                                          archi_table[i].long_archi, argv[1]);
1160                 if (!NT_STATUS_IS_OK(result)) {
1161                         printf ("Failed to remove driver %s for arch [%s] - error %s!\n", 
1162                                 argv[1], archi_table[i].long_archi, get_nt_error_msg(result));
1163                 }
1164                 else
1165                         printf ("Driver %s removed for arch [%s].\n", argv[1], archi_table[i].long_archi);
1166         }
1167                 
1168         return NT_STATUS_OK;            
1169 }
1170
1171 static NTSTATUS cmd_spoolss_getprintprocdir(struct cli_state *cli, 
1172                                             TALLOC_CTX *mem_ctx,
1173                                             int argc, char **argv)
1174 {
1175         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1176         char *servername = NULL, *environment = NULL;
1177         fstring procdir;
1178         
1179         /* parse the command arguements */
1180         if (argc < 2 || argc > 3) {
1181                 printf ("Usage: %s <server> [environment]\n", argv[0]);
1182                 return NT_STATUS_OK;
1183         }
1184
1185         if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
1186                 return NT_STATUS_NO_MEMORY;
1187         strupper(servername);
1188
1189         if (asprintf(&environment, "%s", (argc == 3) ? argv[2] : 
1190                                         PRINTER_DRIVER_ARCHITECTURE) < 0) {
1191                 SAFE_FREE(servername);
1192                 return NT_STATUS_NO_MEMORY;
1193         }
1194
1195         result = cli_spoolss_getprintprocessordirectory(
1196                 cli, mem_ctx, servername, environment, procdir);
1197
1198         if (NT_STATUS_IS_OK(result))
1199                 printf("%s", procdir);
1200
1201         SAFE_FREE(servername);
1202         SAFE_FREE(environment);
1203
1204         return result;
1205 }
1206
1207 /* List of commands exported by this module */
1208 struct cmd_set spoolss_commands[] = {
1209
1210         { "SPOOLSS"  },
1211
1212         { "adddriver",          cmd_spoolss_addprinterdriver,   PIPE_SPOOLSS, "Add a print driver",                  "" },
1213         { "addprinter",         cmd_spoolss_addprinterex,       PIPE_SPOOLSS, "Add a printer",                       "" },
1214         { "deldriver",          cmd_spoolss_deletedriver,       PIPE_SPOOLSS, "Delete a printer driver",             "" },
1215         { "enumdata",           cmd_spoolss_not_implemented,    PIPE_SPOOLSS, "Enumerate printer data (*)",          "" },
1216         { "enumjobs",           cmd_spoolss_not_implemented,    PIPE_SPOOLSS, "Enumerate print jobs (*)",            "" },
1217         { "enumports",          cmd_spoolss_enum_ports,         PIPE_SPOOLSS, "Enumerate printer ports",             "" },
1218         { "enumdrivers",        cmd_spoolss_enum_drivers,       PIPE_SPOOLSS, "Enumerate installed printer drivers", "" },
1219         { "enumprinters",       cmd_spoolss_enum_printers,      PIPE_SPOOLSS, "Enumerate printers",                  "" },
1220         { "getdata",            cmd_spoolss_not_implemented,    PIPE_SPOOLSS, "Get print driver data (*)",           "" },
1221         { "getdriver",          cmd_spoolss_getdriver,          PIPE_SPOOLSS, "Get print driver information",        "" },
1222         { "getdriverdir",       cmd_spoolss_getdriverdir,       PIPE_SPOOLSS, "Get print driver upload directory",   "" },
1223         { "getprinter",         cmd_spoolss_getprinter,         PIPE_SPOOLSS, "Get printer info",                    "" },
1224         { "openprinter",        cmd_spoolss_open_printer_ex,    PIPE_SPOOLSS, "Open printer handle",                 "" },
1225         { "setdriver",          cmd_spoolss_setdriver,          PIPE_SPOOLSS, "Set printer driver",                  "" },
1226         { "getprintprocdir",    cmd_spoolss_getprintprocdir, PIPE_SPOOLSS, "Get print processor directory",          "" },
1227
1228         { NULL }
1229 };