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