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