0c9526b1ec6cd5471d8a3586a22b581274e58b89
[kai/samba.git] / source / printing / nt_printing.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000.
7  *  
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 extern int DEBUGLEVEL;
26
27 /****************************************************************************
28 parse a form line.
29 ****************************************************************************/
30 static BOOL parse_form_entry(char *line, nt_forms_struct *buf)
31 {
32 #define NAMETOK   0
33 #define FLAGTOK   1
34 #define WIDTHTOK  2
35 #define LENGTHTOK 3
36 #define LEFTTOK   4
37 #define TOPTOK    5
38 #define RIGHTTOK  6
39 #define BOTTOMTOK 7
40 #define MAXTOK 8
41         char *tok[MAXTOK];
42         int count = 0;
43
44         tok[0] = strtok(line,":");
45
46         if (!tok[0]) return False;
47         
48         /* strip the comment lines */
49         if (tok[0][0]=='#') return (False);     
50         count++;
51         
52         while ( ((tok[count] = strtok(NULL,":")) != NULL ) && count<MAXTOK-1)
53         {
54                 count++;
55         }
56
57         if (count < MAXTOK-1) return False;
58
59         StrnCpy(buf->name,tok[NAMETOK],sizeof(buf->name)-1);
60         buf->flag=atoi(tok[FLAGTOK]);
61         buf->width=atoi(tok[WIDTHTOK]);
62         buf->length=atoi(tok[LENGTHTOK]);
63         buf->left=atoi(tok[LEFTTOK]);
64         buf->top=atoi(tok[TOPTOK]);
65         buf->right=atoi(tok[RIGHTTOK]);
66         buf->bottom=atoi(tok[BOTTOMTOK]);
67         
68         return(True);
69 }  
70   
71 /****************************************************************************
72 get a form struct list
73 ****************************************************************************/
74 int get_ntforms(nt_forms_struct **list)
75 {
76         char **lines;
77         char *lp_forms = lp_nt_forms();
78         int total=0;
79         int grandtotal=0;
80         int i;
81         
82         lines = file_lines_load(lp_forms, NULL);
83         if (!lines) {
84                 return(0);
85         }
86
87         *list = NULL;
88
89         for (i=0; lines[i]; i++) {
90                 char *line = lines[i];
91
92                 *list = Realloc(*list, sizeof(nt_forms_struct)*(total+1));
93                 if (! *list)
94                 {
95                         total = 0;
96                         break;
97                 }
98                 memset( (char *)&(*list)[total], '\0', sizeof(nt_forms_struct) );
99                 if ( parse_form_entry(line, &(*list)[total] ) )
100                 {
101                         total++;
102                 }
103                 grandtotal++;
104         }    
105
106         file_lines_free(lines);
107
108         return(total);
109 }
110
111 /****************************************************************************
112 write a form struct list
113 ****************************************************************************/
114 int write_ntforms(nt_forms_struct **list, int number)
115 {
116        pstring line;
117        int fd;
118        char *file = lp_nt_forms();
119        int total=0;
120        int i;
121
122        *line=0;
123
124        DEBUG(106,("write_ntforms\n"));
125
126        unlink(file);
127        if((fd = sys_open(file, O_WRONLY|O_CREAT|O_EXCL, 0644)) == -1)
128        {
129                DEBUG(0, ("write_ntforms: Cannot create forms file [%s]. Error was %s\n", file, strerror(errno) ));
130                return(0);
131        }
132
133        for (i=0; i<number;i++)
134        {
135
136                fdprintf(fd,"%s:%d:%d:%d:%d:%d:%d:%d\n", (*list)[i].name,
137                         (*list)[i].flag, (*list)[i].width, (*list)[i].length,
138                         (*list)[i].left, (*list)[i].top, (*list)[i].right, (*list)[i].bottom);
139
140                DEBUGADD(107,("adding entry [%s]\n", (*list)[i].name));
141        }
142
143        close(fd);
144        DEBUGADD(106,("closing file\n"));
145        return(total);
146 }
147
148 /****************************************************************************
149 add a form struct at the end of the list
150 ****************************************************************************/
151 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
152 {
153         int n=0;
154         BOOL update;
155         fstring form_name;
156
157         /* 
158          * NT tries to add forms even when 
159          * they are already in the base
160          * only update the values if already present
161          */
162
163         update=False;
164         
165         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
166         for (n=0; n<*count && update==False; n++)
167         {
168                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
169                 {
170                         DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
171                         update=True;
172                 }
173         }
174
175         if (update==False)
176         {
177                 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
178                         return False;
179                 unistr2_to_ascii((*list)[n].name, &(form->name), sizeof((*list)[n].name)-1);
180                 (*count)++;
181         }
182         
183         (*list)[n].flag=form->flags;
184         (*list)[n].width=form->size_x;
185         (*list)[n].length=form->size_y;
186         (*list)[n].left=form->left;
187         (*list)[n].top=form->top;
188         (*list)[n].right=form->right;
189         (*list)[n].bottom=form->bottom;
190
191         return True;
192 }
193
194 /****************************************************************************
195 update a form struct 
196 ****************************************************************************/
197 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
198 {
199         int n=0;
200         fstring form_name;
201         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
202
203         DEBUG(106, ("[%s]\n", form_name));
204         for (n=0; n<count; n++)
205         {
206                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
207                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
208                         break;
209         }
210
211         if (n==count) return;
212
213         (*list)[n].flag=form->flags;
214         (*list)[n].width=form->size_x;
215         (*list)[n].length=form->size_y;
216         (*list)[n].left=form->left;
217         (*list)[n].top=form->top;
218         (*list)[n].right=form->right;
219         (*list)[n].bottom=form->bottom;
220 }
221  
222 /****************************************************************************
223 get the nt drivers list
224
225 open the directory and look-up the matching names
226 ****************************************************************************/
227 int get_ntdrivers(fstring **list, char *architecture)
228 {
229         DIR *dirp;
230         char *dpname;
231         fstring name_match;
232         fstring short_archi;
233         fstring driver_name;
234         int match_len;
235         int total=0;
236
237         DEBUG(105,("Getting the driver list from directory: [%s]\n", lp_nt_drivers_file()));
238         
239         *list=NULL;
240         dirp = opendir(lp_nt_drivers_file());
241
242         if (dirp == NULL)
243         {
244                 DEBUG(0,("Error opening driver directory [%s]\n",lp_nt_drivers_file())); 
245                 return(-1);
246         }
247         
248         get_short_archi(short_archi, architecture);
249         slprintf(name_match, sizeof(name_match)-1, "NTdriver_%s_", short_archi);
250         match_len=strlen(name_match);
251         
252         while ((dpname = readdirname(dirp)) != NULL)
253         {
254                 if (strncmp(dpname, name_match, match_len)==0)
255                 {
256                         DEBUGADD(107,("Found: [%s]\n", dpname));
257                         
258                         fstrcpy(driver_name, dpname+match_len);
259                         all_string_sub(driver_name, "#", "/", 0);
260
261                         if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
262                                 return -1;
263
264                         StrnCpy((*list)[total], driver_name, strlen(driver_name));
265                         DEBUGADD(106,("Added: [%s]\n", driver_name));           
266                         total++;
267                 }
268         }
269
270         closedir(dirp);
271         return(total);
272 }
273
274 /****************************************************************************
275 function to do the mapping between the long architecture name and
276 the short one.
277 ****************************************************************************/
278 void get_short_archi(char *short_archi, char *long_archi)
279 {
280         struct table {
281                 char *long_archi;
282                 char *short_archi;
283         };
284         
285         struct table archi_table[]=
286         {
287                 {"Windows 4.0",          "WIN40"    },
288                 {"Windows NT x86",       "W32X86"   },
289                 {"Windows NT R4000",     "W32mips"  },
290                 {"Windows NT Alpha_AXP", "W32alpha" },
291                 {"Windows NT PowerPC",   "W32ppc"   },
292                 {NULL,                   ""         }
293         };
294         
295         int i=-1;
296
297         DEBUG(107,("Getting architecture dependant directory\n"));
298         do {
299                 i++;
300         } while ( (archi_table[i].long_archi!=NULL ) && strncmp(long_archi, archi_table[i].long_archi, strlen(long_archi)) );
301
302         if (archi_table[i].long_archi==NULL)
303         {
304                 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
305         }
306         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
307
308         DEBUGADD(108,("index: [%d]\n", i));
309         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
310         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
311 }
312
313 /****************************************************************************
314 ****************************************************************************/
315 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
316 {
317         int fd;
318         pstring file;
319         fstring architecture;
320         fstring driver_name;
321         char **dependentfiles;
322
323         /* create a file in the dir lp_nt_driver_file */
324         /* with the full printer DRIVER name */
325         /* eg: "/usr/local/samba/lib/NTdriver_HP LaserJet 6MP" */
326         /* each name is really defining an *unique* printer model */
327         /* I don't want to mangle the name to find it back when enumerating */
328
329         /* il faut substituer les / par 1 autre caractere d'abord */
330         /* dans le nom de l'imprimante par un # ???*/
331
332         StrnCpy(driver_name, driver->name, sizeof(driver_name)-1);
333
334         all_string_sub(driver_name, "/", "#", 0);
335
336         get_short_archi(architecture, driver->environment);
337                 
338         slprintf(file, sizeof(file)-1, "%s/NTdriver_%s_%s",
339                  lp_nt_drivers_file(), architecture, driver_name);
340
341         unlink(file);
342         if((fd = sys_open(file, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644)) == -1)
343         {
344                 DEBUG(0, ("add_a_printer_driver_3: Cannot create driver file [%s]. Error was %s\n", file, strerror(errno) ));
345                 return(2);
346         }
347
348         /*
349          * cversion must be 2.
350          * when adding a printer ON the SERVER
351          * rpcAddPrinterDriver defines it to zero
352          * which is wrong !!!
353          *
354          * JFM, 4/14/99
355          */
356         driver->cversion=2;
357         
358         fdprintf(fd, "version:         %d\n", driver->cversion);
359         fdprintf(fd, "name:            %s\n", driver->name);
360         fdprintf(fd, "environment:     %s\n", driver->environment);
361         fdprintf(fd, "driverpath:      %s\n", driver->driverpath);
362         fdprintf(fd, "datafile:        %s\n", driver->datafile);
363         fdprintf(fd, "configfile:      %s\n", driver->configfile);
364         fdprintf(fd, "helpfile:        %s\n", driver->helpfile);
365         fdprintf(fd, "monitorname:     %s\n", driver->monitorname);
366         fdprintf(fd, "defaultdatatype: %s\n", driver->defaultdatatype);
367
368         /* and the dependants files */
369         
370         dependentfiles=driver->dependentfiles;
371         
372         while ( **dependentfiles != '\0' )
373         {
374                 fdprintf(fd, "dependentfile:   %s\n", *dependentfiles);
375                 dependentfiles++;
376         }
377         
378         close(fd);      
379         return(0);
380 }
381
382 /****************************************************************************
383 ****************************************************************************/
384 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
385 {
386         char **lines;
387         int lcount;
388         pstring file;
389         fstring driver_name;
390         fstring architecture;
391         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info = NULL;
392         fstring p;
393         char *v;
394         int i=0;
395         char **dependentfiles=NULL;
396         
397         /*
398          * replace all the / by # in the driver name
399          * get the short architecture name
400          * construct the driver file name
401          */
402         StrnCpy(driver_name, in_prt, sizeof(driver_name)-1);
403         all_string_sub(driver_name, "/", "#", 0);
404
405         get_short_archi(architecture, in_arch);
406                 
407         slprintf(file, sizeof(file)-1, "%s/NTdriver_%s_%s",
408                  lp_nt_drivers_file(), architecture, driver_name);
409
410         lines = file_lines_load(file, NULL);
411
412         if (!lines) {
413                 DEBUG(2, ("get_a_printer_driver_3: Cannot open printer driver file [%s]. Error was %s\n", file, strerror(errno) ));
414                 return(2);
415         }
416
417         /* the file exists, allocate some memory */
418         if((info=(NT_PRINTER_DRIVER_INFO_LEVEL_3 *)malloc(sizeof(NT_PRINTER_DRIVER_INFO_LEVEL_3))) == NULL)
419                 goto err;
420
421         ZERO_STRUCTP(info);
422         
423         for (lcount=0; lines[lcount]; lcount++) {
424                 char *line = lines[lcount];
425                 v=strncpyn(p, line, sizeof(p), ':');
426                 if (v==NULL)
427                 {
428                         DEBUG(1, ("malformed printer driver entry (no :)\n"));
429                         continue;
430                 }
431                 
432                 v++;
433                 
434                 trim_string(v, " ", NULL);
435                 trim_string(v, NULL, " ");
436                 trim_string(v, NULL, "\n");
437                 /* don't check if v==NULL as an empty arg is valid */
438                 
439                 if (!strncmp(p, "version", strlen("version")))
440                         info->cversion=atoi(v);
441
442                 if (!strncmp(p, "name", strlen("name")))
443                         StrnCpy(info->name, v, strlen(v));
444
445                 if (!strncmp(p, "environment", strlen("environment")))
446                         StrnCpy(info->environment, v, strlen(v));
447
448                 if (!strncmp(p, "driverpath", strlen("driverpath")))
449                         StrnCpy(info->driverpath, v, strlen(v));
450
451                 if (!strncmp(p, "datafile", strlen("datafile")))
452                         StrnCpy(info->datafile, v, strlen(v));
453
454                 if (!strncmp(p, "configfile", strlen("configfile")))
455                         StrnCpy(info->configfile, v, strlen(v));
456
457                 if (!strncmp(p, "helpfile", strlen("helpfile")))
458                         StrnCpy(info->helpfile, v, strlen(v));
459
460                 if (!strncmp(p, "monitorname", strlen("monitorname")))
461                         StrnCpy(info->monitorname, v, strlen(v));
462
463                 if (!strncmp(p, "defaultdatatype", strlen("defaultdatatype")))
464                         StrnCpy(info->defaultdatatype, v, strlen(v));
465
466                 if (!strncmp(p, "dependentfile", strlen("dependentfile")))
467                 {
468                         if((dependentfiles=(char **)Realloc(dependentfiles, sizeof(char *)*(i+1))) == NULL)
469                                 goto err;
470                         
471                         if((dependentfiles[i]=(char *)malloc( sizeof(char)* (strlen(v)+1) )) == NULL)
472                                 goto err;
473                         
474                         StrnCpy(dependentfiles[i], v, strlen(v) );
475                         i++;
476                 }
477         }
478         
479         file_lines_free(lines);
480         
481         dependentfiles=(char **)Realloc(dependentfiles, sizeof(char *)*(i+1));
482         dependentfiles[i]=(char *)malloc( sizeof(char) );
483         *dependentfiles[i]='\0';
484         
485         info->dependentfiles=dependentfiles;
486         
487         *info_ptr=info;
488         
489         return (0);     
490
491   err:
492
493         if (lines)
494                 file_lines_free(lines);
495         if(info)
496                 free(info);
497
498         if(dependentfiles) {
499                 for(;i >= 0; i--)
500                         if(dependentfiles[i])
501                                 free(dependentfiles[i]);
502
503                 free(dependentfiles);
504         }
505
506         return (2);
507 }
508
509 /****************************************************************************
510 debugging function, dump at level 6 the struct in the logs
511 ****************************************************************************/
512 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
513 {
514         uint32 success;
515         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
516         char **dependentfiles;  
517         
518         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
519         
520         switch (level)
521         {
522                 case 3: 
523                 {
524                         if (driver.info_3 == NULL)
525                                 success=5;
526                         else {
527                                 info3=driver.info_3;
528                         
529                                 DEBUGADD(106,("version:[%d]\n",         info3->cversion));
530                                 DEBUGADD(106,("name:[%s]\n",            info3->name));
531                                 DEBUGADD(106,("environment:[%s]\n",     info3->environment));
532                                 DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
533                                 DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
534                                 DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
535                                 DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
536                                 DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
537                                 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
538                                 
539                                 dependentfiles=info3->dependentfiles;
540         
541                                 while ( **dependentfiles != '\0' )
542                                 {
543                                         DEBUGADD(106,("dependentfile:[%s]\n", *dependentfiles));
544                                         dependentfiles++;
545                                 }
546                                 success=0;
547                         }
548                         break;
549                 }
550                 default:
551                         DEBUGADD(1,("Level not implemented\n"));
552                         success=1;
553                         break;
554         }
555         
556         return (success);
557 }
558
559 /****************************************************************************
560 ****************************************************************************/
561 static void add_a_devicemode(NT_DEVICEMODE *nt_devmode, int fd)
562 {
563         int i;
564         
565         fdprintf(fd, "formname: %s\n",      nt_devmode->formname);
566         fdprintf(fd, "specversion: %d\n",   nt_devmode->specversion);
567         fdprintf(fd, "driverversion: %d\n", nt_devmode->driverversion);
568         fdprintf(fd, "size: %d\n",          nt_devmode->size);
569         fdprintf(fd, "driverextra: %d\n",   nt_devmode->driverextra);
570         fdprintf(fd, "fields: %d\n",        nt_devmode->fields);
571         fdprintf(fd, "orientation: %d\n",   nt_devmode->orientation);
572         fdprintf(fd, "papersize: %d\n",     nt_devmode->papersize);
573         fdprintf(fd, "paperlength: %d\n",   nt_devmode->paperlength);
574         fdprintf(fd, "paperwidth: %d\n",    nt_devmode->paperwidth);
575         fdprintf(fd, "scale: %d\n",         nt_devmode->scale);
576         fdprintf(fd, "copies: %d\n",        nt_devmode->copies);
577         fdprintf(fd, "defaultsource: %d\n", nt_devmode->defaultsource);
578         fdprintf(fd, "printquality: %d\n",  nt_devmode->printquality);
579         fdprintf(fd, "color: %d\n",         nt_devmode->color);
580         fdprintf(fd, "duplex: %d\n",        nt_devmode->duplex);
581         fdprintf(fd, "yresolution: %d\n",   nt_devmode->yresolution);
582         fdprintf(fd, "ttoption: %d\n",      nt_devmode->ttoption);
583         fdprintf(fd, "collate: %d\n",       nt_devmode->collate);
584         fdprintf(fd, "icmmethod: %d\n",     nt_devmode->icmmethod);
585         fdprintf(fd, "icmintent: %d\n",     nt_devmode->icmintent);
586         fdprintf(fd, "mediatype: %d\n",     nt_devmode->mediatype);
587         fdprintf(fd, "dithertype: %d\n",    nt_devmode->dithertype);
588         
589         if (nt_devmode->private != NULL)
590         {
591                 fdprintf(fd, "private: ");              
592                 for (i=0; i<nt_devmode->driverextra; i++)
593                         fdprintf(fd, "%02X", nt_devmode->private[i]);
594                 fdprintf(fd, "\n");     
595         }
596 }
597
598 /****************************************************************************
599 ****************************************************************************/
600 static void save_specifics(NT_PRINTER_PARAM *param, int fd)
601 {
602         int i;
603         
604         while (param != NULL)
605         {
606                 fdprintf(fd, "specific: %s#%d#%d#", param->value, param->type, param->data_len);
607                 
608                 for (i=0; i<param->data_len; i++)
609                         fdprintf(fd, "%02X", param->data[i]);
610                 
611                 fdprintf(fd, "\n");
612         
613                 param=param->next;      
614         }
615 }
616
617 /****************************************************************************
618 ****************************************************************************/
619 static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
620 {
621         int fd;
622         pstring file;
623         fstring printer_name;
624         NT_DEVICEMODE *nt_devmode;
625         
626         /*
627          * JFM: one day I'll forget.
628          * below that's info->portname because that's the SAMBA sharename
629          * and I made NT 'thinks' it's the portname
630          * the info->sharename is the thing you can name when you add a printer
631          * that's the short-name when you create shared printer for 95/98
632          * So I've made a limitation in SAMBA: you can only have 1 printer model
633          * behind a SAMBA share.
634          */
635
636
637         StrnCpy(printer_name, info->portname, sizeof(printer_name)-1);
638                 
639         slprintf(file, sizeof(file)-1, "%s/NTprinter_%s",
640                  lp_nt_drivers_file(), printer_name);
641
642         /* create a file in the dir lp_nt_driver_file */
643         /* with the full printer name */
644         /* eg: "/usr/local/samba/lib/NTprinter_HP LaserJet 6MP" */
645         /* each name is really defining an *unique* printer model */
646         /* I don't want to mangle the name to find it back when enumerating */
647         
648         unlink(file);
649         if((fd = sys_open(file, O_WRONLY|O_CREAT|O_EXCL, 0644)) == -1)
650         {
651                 DEBUG(0, ("add_a_printer_2: Cannot create printer file [%s]. Error was %s\n", file, strerror(errno) ));
652                 return(2);
653         }
654
655         fdprintf(fd, "attributes: %d\n", info->attributes);
656         fdprintf(fd, "priority: %d\n", info->priority);
657         fdprintf(fd, "default_priority: %d\n", info->default_priority);
658         fdprintf(fd, "starttime: %d\n", info->starttime);
659         fdprintf(fd, "untiltime: %d\n", info->untiltime);
660         fdprintf(fd, "status: %d\n", info->status);
661         fdprintf(fd, "cjobs: %d\n", info->cjobs);
662         fdprintf(fd, "averageppm: %d\n", info->averageppm);
663         fdprintf(fd, "changeid: %d\n", info->changeid);
664         fdprintf(fd, "c_setprinter: %d\n", info->c_setprinter);
665         fdprintf(fd, "setuptime: %d\n", (int)info->setuptime);
666
667         /* 
668          * in addprinter: no servername and the printer is the name
669          * in setprinter: servername is \\server
670          *                and printer is \\server\\printer
671          *
672          * Samba manages only local printers.
673          * we currently don't support things like path=\\other_server\printer
674          */
675
676         if (info->servername[0]!='\0')
677         {
678                 trim_string(info->printername, info->servername, NULL);
679                 trim_string(info->printername, "\\", NULL);
680                 info->servername[0]='\0';
681         }
682
683         fdprintf(fd, "servername: %s\n", info->servername);
684         fdprintf(fd, "printername: %s\n", info->printername);
685         fdprintf(fd, "sharename: %s\n", info->sharename);
686         fdprintf(fd, "portname: %s\n", info->portname);
687         fdprintf(fd, "drivername: %s\n", info->drivername);
688         fdprintf(fd, "location: %s\n", info->location);
689         fdprintf(fd, "sepfile: %s\n", info->sepfile);
690         fdprintf(fd, "printprocessor: %s\n", info->printprocessor);
691         fdprintf(fd, "datatype: %s\n", info->datatype);
692         fdprintf(fd, "parameters: %s\n", info->parameters);
693
694         /* store the devmode and the private part if it exist */
695         nt_devmode=info->devmode;
696         if (nt_devmode!=NULL)
697         {
698                 add_a_devicemode(nt_devmode, fd);
699         }
700         
701         /* and store the specific parameters */
702         if (info->specific != NULL)
703         {
704                 save_specifics(info->specific, fd);
705         }
706         
707         close(fd);
708         
709         return (0);     
710 }
711
712 /****************************************************************************
713 fill a NT_PRINTER_PARAM from a text file
714
715 used when reading from disk.
716 ****************************************************************************/
717 static BOOL dissect_and_fill_a_param(NT_PRINTER_PARAM *param, char *v)
718 {
719         char *tok[5];
720         int count = 0;
721
722         DEBUG(105,("dissect_and_fill_a_param\n"));      
723                 
724         tok[count] = strtok(v,"#");
725         count++;
726         
727         while ( ((tok[count] = strtok(NULL,"#")) != NULL ) && count<4)
728         {
729                 count++;
730         }
731
732         StrnCpy(param->value, tok[0], sizeof(param->value)-1);
733         param->type=atoi(tok[1]);
734         param->data_len=atoi(tok[2]);
735         if((param->data=(uint8 *)malloc(param->data_len * sizeof(uint8))) == NULL)
736                 return False;
737         strhex_to_str(param->data, 2*(param->data_len), tok[3]);                
738         param->next=NULL;       
739
740         DEBUGADD(105,("value:[%s], len:[%d]\n", param->value, param->data_len));
741         return True;
742 }
743
744 /****************************************************************************
745 fill a NT_PRINTER_PARAM from a text file
746
747 used when reading from disk.
748 ****************************************************************************/
749 void dump_a_param(NT_PRINTER_PARAM *param)
750 {
751         DEBUG(105,("dump_a_param\n"));
752         DEBUGADD(106,("value [%s]\n", param->value));
753         DEBUGADD(106,("type [%d]\n", param->type));
754         DEBUGADD(106,("data len [%d]\n", param->data_len));
755 }
756
757 /****************************************************************************
758 ****************************************************************************/
759 BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
760 {
761         NT_PRINTER_PARAM *current;
762         
763         DEBUG(108,("add_a_specific_param\n"));  
764
765         param->next=NULL;
766         
767         if (info_2->specific == NULL)
768         {
769                 info_2->specific=param;
770         }
771         else
772         {
773                 current=info_2->specific;               
774                 while (current->next != NULL) {
775                         current=current->next;
776                 }               
777                 current->next=param;
778         }
779         return (True);
780 }
781
782 /****************************************************************************
783 ****************************************************************************/
784 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
785 {
786         NT_PRINTER_PARAM *current;
787         NT_PRINTER_PARAM *previous;
788         
789         current=info_2->specific;
790         previous=current;
791         
792         if (current==NULL) return (False);
793         
794         if ( !strcmp(current->value, param->value) && 
795             (strlen(current->value)==strlen(param->value)) )
796         {
797                 DEBUG(109,("deleting first value\n"));
798                 info_2->specific=current->next;
799                 safe_free(current->data);
800                 free(current);
801                 DEBUG(109,("deleted first value\n"));
802                 return (True);
803         }
804
805         current=previous->next;
806                 
807         while ( current!=NULL )
808         {
809                 if (!strcmp(current->value, param->value) &&
810                     strlen(current->value)==strlen(param->value) )
811                 {
812                         DEBUG(109,("deleting current value\n"));
813                         previous->next=current->next;
814                         free(current);
815                         DEBUG(109,("deleted current value\n"));
816                         return(True);
817                 }
818                 
819                 previous=previous->next;
820                 current=current->next;
821         }
822         return (False);
823 }
824
825 /****************************************************************************
826  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
827 ****************************************************************************/
828
829 static void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
830 {
831         NT_PRINTER_PARAM *param = *param_ptr;
832
833         if(param == NULL)
834                 return;
835
836         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
837
838         if(param->data)
839                 free(param->data);
840
841         free(param);
842         *param_ptr = NULL;
843 }
844
845 /****************************************************************************
846  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
847 ****************************************************************************/
848
849 static void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
850 {
851         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
852
853         if(nt_devmode == NULL)
854                 return;
855
856         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
857
858         if(nt_devmode->private)
859                 free(nt_devmode->private);
860
861         free(nt_devmode);
862         *devmode_ptr = NULL;
863 }
864
865 /****************************************************************************
866  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
867 ****************************************************************************/
868
869 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
870 {
871         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
872         NT_PRINTER_PARAM *param_ptr;
873
874         if(info == NULL)
875                 return;
876
877         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
878
879         free_nt_devicemode(&info->devmode);
880
881         for(param_ptr = info->specific; param_ptr; ) {
882                 NT_PRINTER_PARAM *tofree = param_ptr;
883
884                 param_ptr = param_ptr->next;
885                 free_nt_printer_param(&tofree);
886         }
887
888         free(info);
889         *info_ptr = NULL;
890 }
891
892 /****************************************************************************
893 ****************************************************************************/
894 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
895 {
896         pstring file;
897         fstring printer_name;
898         NT_PRINTER_INFO_LEVEL_2 *info = NULL;
899         NT_DEVICEMODE *nt_devmode = NULL;
900         NT_PRINTER_PARAM *param = NULL;
901         fstring p;
902         char *v = NULL;
903         char **lines;
904         int i;
905                 
906         /*
907          * the sharename argument is the SAMBA sharename
908          */
909         StrnCpy(printer_name, sharename, sizeof(printer_name)-1);
910                 
911         slprintf(file, sizeof(file)-1, "%s/NTprinter_%s",
912                  lp_nt_drivers_file(), printer_name);
913
914         lines = file_lines_load(file,NULL);
915         if(lines == NULL) {
916                 DEBUG(2, ("get_a_printer_2: Cannot open printer file [%s]. Error was %s\n", file, strerror(errno) ));
917                 return(2);
918         }
919
920         /* the file exists, allocate some memory */
921         if((info=(NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) == NULL)
922                 goto err;
923
924         ZERO_STRUCTP(info);
925
926         if((nt_devmode=(NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE))) == NULL)
927                 goto err;
928
929         ZERO_STRUCTP(nt_devmode);
930         init_devicemode(nt_devmode);
931         
932         info->devmode=nt_devmode;
933
934         for (i=0; lines[i]; i++) {
935                 char *line = lines[i];
936
937                 if (!*line) continue;
938
939                 v=strncpyn(p, line, sizeof(p), ':');
940                 if (v==NULL)
941                 {
942                         DEBUG(1, ("malformed printer entry (no `:')\n"));
943                         DEBUGADD(2, ("line [%s]\n", line));             
944                         continue;
945                 }
946                 
947                 v++;
948                 
949                 trim_string(v, " ", NULL);
950                 trim_string(v, NULL, " ");
951                 trim_string(v, NULL, "\n");
952                 
953                 /* don't check if v==NULL as an empty arg is valid */
954                 
955                 DEBUGADD(115, ("[%s]:[%s]\n", p, v));
956
957                 /*
958                  * The PRINTER_INFO_2 fields
959                  */
960                 
961                 if (!strncmp(p, "attributes", strlen("attributes")))
962                         info->attributes=atoi(v);
963
964                 if (!strncmp(p, "priority", strlen("priority")))
965                         info->priority=atoi(v);
966
967                 if (!strncmp(p, "default_priority", strlen("default_priority")))
968                         info->default_priority=atoi(v);
969
970                 if (!strncmp(p, "starttime", strlen("starttime")))
971                         info->starttime=atoi(v);
972
973                 if (!strncmp(p, "untiltime", strlen("untiltime")))
974                         info->untiltime=atoi(v);
975
976                 if (!strncmp(p, "status", strlen("status")))
977                         info->status=atoi(v);
978
979                 if (!strncmp(p, "cjobs", strlen("cjobs")))
980                         info->cjobs=atoi(v);
981
982                 if (!strncmp(p, "averageppm", strlen("averageppm")))
983                         info->averageppm=atoi(v);
984                 
985                 if (!strncmp(p, "changeid", strlen("changeid")))
986                         info->changeid=atoi(v);
987                 
988                 if (!strncmp(p, "c_setprinter", strlen("c_setprinter")))
989                         info->c_setprinter=atoi(v);
990                 
991                 if (!strncmp(p, "setuptime", strlen("setuptime")))
992                         info->setuptime=atoi(v);
993                 
994                 if (!strncmp(p, "servername", strlen("servername")))
995                         StrnCpy(info->servername, v, strlen(v));
996
997                 if (!strncmp(p, "printername", strlen("printername")))
998                         StrnCpy(info->printername, v, strlen(v));
999
1000                 if (!strncmp(p, "sharename", strlen("sharename")))
1001                         StrnCpy(info->sharename, v, strlen(v));
1002
1003                 if (!strncmp(p, "portname", strlen("portname")))
1004                         StrnCpy(info->portname, v, strlen(v));
1005
1006                 if (!strncmp(p, "drivername", strlen("drivername")))
1007                         StrnCpy(info->drivername, v, strlen(v));
1008
1009                 if (!strncmp(p, "location", strlen("location")))
1010                         StrnCpy(info->location, v, strlen(v));
1011
1012                 if (!strncmp(p, "sepfile", strlen("sepfile")))
1013                         StrnCpy(info->sepfile, v, strlen(v));
1014
1015                 if (!strncmp(p, "printprocessor", strlen("printprocessor")))
1016                         StrnCpy(info->printprocessor, v, strlen(v));
1017
1018                 if (!strncmp(p, "datatype", strlen("datatype")))
1019                         StrnCpy(info->datatype, v, strlen(v));
1020
1021                 if (!strncmp(p, "parameters", strlen("parameters")))
1022                         StrnCpy(info->parameters, v, strlen(v));
1023
1024                 /*
1025                  * The DEVICEMODE fields
1026                  */
1027
1028                 if (!strncmp(p, "formname", strlen("formname")))
1029                         StrnCpy(nt_devmode->formname, v, strlen(v));
1030                         
1031                 if (!strncmp(p, "specversion", strlen("specversion")))
1032                         nt_devmode->specversion=atoi(v);
1033
1034                 if (!strncmp(p, "driverversion", strlen("driverversion")))
1035                         nt_devmode->driverversion=atoi(v);
1036
1037                 if (!strncmp(p, "size", strlen("size")))
1038                         nt_devmode->size=atoi(v);
1039
1040                 if (!strncmp(p, "driverextra", strlen("driverextra")))
1041                         nt_devmode->driverextra=atoi(v);
1042
1043                 if (!strncmp(p, "fields", strlen("fields")))
1044                         nt_devmode->fields=atoi(v);
1045
1046                 if (!strncmp(p, "orientation", strlen("orientation")))
1047                         nt_devmode->orientation=atoi(v);
1048
1049                 if (!strncmp(p, "papersize", strlen("papersize")))
1050                         nt_devmode->papersize=atoi(v);
1051
1052                 if (!strncmp(p, "paperlength", strlen("paperlength")))
1053                         nt_devmode->paperlength=atoi(v);
1054
1055                 if (!strncmp(p, "paperwidth", strlen("paperwidth")))
1056                         nt_devmode->paperwidth=atoi(v);
1057
1058                 if (!strncmp(p, "scale", strlen("scale")))
1059                         nt_devmode->scale=atoi(v);
1060
1061                 if (!strncmp(p, "copies", strlen("copies")))
1062                         nt_devmode->copies=atoi(v);
1063
1064                 if (!strncmp(p, "defaultsource", strlen("defaultsource")))
1065                         nt_devmode->defaultsource=atoi(v);
1066
1067                 if (!strncmp(p, "printquality", strlen("printquality")))
1068                         nt_devmode->printquality=atoi(v);
1069
1070                 if (!strncmp(p, "color", strlen("color")))
1071                         nt_devmode->color=atoi(v);
1072
1073                 if (!strncmp(p, "duplex", strlen("duplex")))
1074                         nt_devmode->duplex=atoi(v);
1075
1076                 if (!strncmp(p, "yresolution", strlen("yresolution")))
1077                         nt_devmode->yresolution=atoi(v);
1078
1079                 if (!strncmp(p, "ttoption", strlen("ttoption")))
1080                         nt_devmode->ttoption=atoi(v);
1081
1082                 if (!strncmp(p, "collate", strlen("collate")))
1083                         nt_devmode->collate=atoi(v);
1084
1085                 if (!strncmp(p, "icmmethod", strlen("icmmethod")))
1086                         nt_devmode->icmmethod=atoi(v);
1087
1088                 if (!strncmp(p, "icmintent", strlen("icmintent")))
1089                         nt_devmode->icmintent=atoi(v);
1090
1091                 if (!strncmp(p, "mediatype", strlen("mediatype")))
1092                         nt_devmode->mediatype=atoi(v);
1093
1094                 if (!strncmp(p, "dithertype", strlen("dithertype")))
1095                         nt_devmode->dithertype=atoi(v);
1096                         
1097                 if (!strncmp(p, "private", strlen("private")))
1098                 {
1099                         if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra*sizeof(uint8))) == NULL)
1100                                 goto err;
1101
1102                         strhex_to_str(nt_devmode->private, 2*nt_devmode->driverextra, v);
1103                 }
1104                 
1105                 /* the specific */
1106                 
1107                 if (!strncmp(p, "specific", strlen("specific")))
1108                 {
1109                         if((param=(NT_PRINTER_PARAM *)malloc(sizeof(NT_PRINTER_PARAM))) == NULL)
1110                                 goto err;
1111
1112                         ZERO_STRUCTP(param);
1113                         
1114                         if(!dissect_and_fill_a_param(param, v))
1115                                 goto err;
1116                         
1117                         dump_a_param(param);
1118                         
1119                         add_a_specific_param(info, param);
1120                 }
1121                 
1122         }
1123         file_lines_free(lines);
1124         
1125         *info_ptr=info;
1126         
1127         return (0);     
1128
1129   err:
1130
1131         if(lines)
1132                 file_lines_free(lines);
1133         if(info)
1134                 free_nt_printer_info_level_2(&info);
1135         return(2);
1136 }
1137
1138 /****************************************************************************
1139 debugging function, dump at level 6 the struct in the logs
1140 ****************************************************************************/
1141 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1142 {
1143         uint32 success;
1144         NT_PRINTER_INFO_LEVEL_2 *info2;
1145         
1146         DEBUG(106,("Dumping printer at level [%d]\n", level));
1147         
1148         switch (level)
1149         {
1150                 case 2: 
1151                 {
1152                         if (printer.info_2 == NULL)
1153                                 success=5;
1154                         else
1155                         {
1156                                 info2=printer.info_2;
1157                         
1158                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
1159                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
1160                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
1161                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
1162                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
1163                                 DEBUGADD(106,("status:[%d]\n", info2->status));
1164                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
1165                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
1166                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
1167                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
1168                                 DEBUGADD(106,("setuptime:[%d]\n", (int)info2->setuptime));
1169
1170                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
1171                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
1172                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
1173                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
1174                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
1175                                 DEBUGADD(106,("location:[%s]\n", info2->location));
1176                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
1177                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
1178                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
1179                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
1180                                 success=0;
1181                         }
1182                         break;
1183                 }
1184                 default:
1185                         DEBUGADD(1,("Level not implemented\n"));
1186                         success=1;
1187                         break;
1188         }
1189         
1190         return (success);
1191 }
1192
1193 /*
1194  * The function below are the high level ones.
1195  * only those ones must be called from the spoolss code.
1196  * JFM.
1197  */
1198
1199
1200 /****************************************************************************
1201 ****************************************************************************/
1202 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1203 {
1204         uint32 success;
1205         
1206         dump_a_printer(printer, level); 
1207         
1208         switch (level)
1209         {
1210                 case 2: 
1211                 {
1212                         success=add_a_printer_2(printer.info_2);
1213                         break;
1214                 }
1215                 default:
1216                         success=1;
1217                         break;
1218         }
1219         
1220         return (success);
1221 }
1222
1223 /****************************************************************************
1224 ****************************************************************************/
1225 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level, fstring sharename)
1226 {
1227         uint32 success;
1228         
1229         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
1230
1231         switch (level)
1232         {
1233                 case 2: 
1234                 {
1235                         printer->info_2=NULL;
1236                         success=get_a_printer_2(&(printer->info_2), sharename);
1237                         break;
1238                 }
1239                 default:
1240                         success=1;
1241                         break;
1242         }
1243         
1244         dump_a_printer(*printer, level);
1245
1246         DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
1247
1248         return (success);
1249 }
1250
1251 /****************************************************************************
1252 ****************************************************************************/
1253 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1254 {
1255         uint32 success;
1256         DEBUG(104,("freeing a printer at level [%d]\n", level));
1257         
1258         switch (level)
1259         {
1260                 case 2: 
1261                 {
1262                         if (printer.info_2 != NULL)
1263                         {
1264                                 free_nt_printer_info_level_2(&printer.info_2);
1265                                 success=0;
1266                         }
1267                         else
1268                         {
1269                                 success=4;
1270                         }
1271                         break;
1272                 }
1273                 default:
1274                         success=1;
1275                         break;
1276         }
1277         return (success);
1278 }
1279
1280 /****************************************************************************
1281 ****************************************************************************/
1282 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1283 {
1284         uint32 success;
1285         DEBUG(104,("adding a printer at level [%d]\n", level));
1286         dump_a_printer_driver(driver, level);
1287         
1288         switch (level)
1289         {
1290                 case 3: 
1291                 {
1292                         success=add_a_printer_driver_3(driver.info_3);
1293                         break;
1294                 }
1295                 default:
1296                         success=1;
1297                         break;
1298         }
1299         
1300         return (success);
1301 }
1302 /****************************************************************************
1303 ****************************************************************************/
1304 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, 
1305                             fstring printername, fstring architecture)
1306 {
1307         uint32 success;
1308         
1309         switch (level)
1310         {
1311                 case 3: 
1312                 {
1313                         success=get_a_printer_driver_3(&(driver->info_3), 
1314                                                        printername,
1315                                                        architecture);
1316                         break;
1317                 }
1318                 default:
1319                         success=1;
1320                         break;
1321         }
1322         
1323         dump_a_printer_driver(*driver, level);
1324         return (success);
1325 }
1326
1327 /****************************************************************************
1328 ****************************************************************************/
1329 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1330 {
1331         uint32 success;
1332         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1333         char **dependentfiles;
1334         
1335         switch (level)
1336         {
1337                 case 3: 
1338                 {
1339                         if (driver.info_3 != NULL)
1340                         {
1341                                 info3=driver.info_3;
1342                                 dependentfiles=info3->dependentfiles;
1343         
1344                                 while ( **dependentfiles != '\0' )
1345                                 {
1346                                         free (*dependentfiles);
1347                                         dependentfiles++;
1348                                 }
1349                                 
1350                                 /* the last one (1 char !) */
1351                                 free (*dependentfiles);
1352                                 
1353                                 dependentfiles=info3->dependentfiles;
1354                                 free (dependentfiles);
1355                                 
1356                                 free(info3);
1357                                 success=0;
1358                         }
1359                         else
1360                         {
1361                                 success=4;
1362                         }
1363                         break;
1364                 }
1365                 default:
1366                         success=1;
1367                         break;
1368         }
1369         return (success);
1370 }
1371
1372 /****************************************************************************
1373 ****************************************************************************/
1374 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
1375                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
1376 {
1377         /* right now that's enough ! */ 
1378         NT_PRINTER_PARAM *param;
1379         int i=0;
1380         
1381         param=printer.info_2->specific;
1382         
1383         while (param != NULL && i <= param_index)
1384         {
1385                 param=param->next;
1386                 i++;
1387         }
1388         
1389         if (param == NULL)
1390                 return False;
1391
1392         /* exited because it exist */
1393         *type=param->type;              
1394         StrnCpy(value, param->value, sizeof(fstring)-1);
1395         *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1396         if(*data == NULL)
1397                 return False;
1398         memcpy(*data, param->data, param->data_len);
1399         *len=param->data_len;
1400         return True;
1401 }
1402
1403 /****************************************************************************
1404 ****************************************************************************/
1405 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, 
1406                         fstring value, uint8 **data, uint32 *type, uint32 *len)
1407 {
1408         /* right now that's enough ! */ 
1409         NT_PRINTER_PARAM *param;
1410         
1411         DEBUG(105, ("get_specific_param\n"));
1412         
1413         param=printer.info_2->specific;
1414                 
1415         while (param != NULL)
1416         {
1417                 if ( !strcmp(value, param->value) 
1418                     && strlen(value)==strlen(param->value))
1419                         break;
1420                         
1421                 param=param->next;
1422         }
1423         
1424         DEBUG(106, ("found one param\n"));
1425         if (param != NULL)
1426         {
1427                 /* exited because it exist */
1428                 *type=param->type;      
1429                 
1430                 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1431                 if(*data == NULL)
1432                         return False;
1433                 memcpy(*data, param->data, param->data_len);
1434                 *len=param->data_len;
1435
1436                 DEBUG(106, ("exit of get_specific_param:true\n"));
1437                 return (True);
1438         }
1439         DEBUG(106, ("exit of get_specific_param:false\n"));
1440         return (False);
1441 }
1442
1443 /****************************************************************************
1444 ****************************************************************************/
1445 void init_devicemode(NT_DEVICEMODE *nt_devmode)
1446 {
1447 /*
1448  * should I init this ones ???
1449         nt_devmode->devicename
1450 */
1451         fstrcpy(nt_devmode->formname, "A4");
1452
1453         nt_devmode->specversion      = 0x0401;
1454         nt_devmode->driverversion    = 0x0400;
1455         nt_devmode->size             = 0x00DC;
1456         nt_devmode->driverextra      = 0x0000;
1457         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY | 
1458                                        DEFAULTSOURCE | COPIES | SCALE | 
1459                                        PAPERSIZE | ORIENTATION;
1460         nt_devmode->orientation      = 1;
1461         nt_devmode->papersize        = PAPER_A4;
1462         nt_devmode->paperlength      = 0;
1463         nt_devmode->paperwidth       = 0;
1464         nt_devmode->scale            = 0x64;
1465         nt_devmode->copies           = 01;
1466         nt_devmode->defaultsource    = BIN_FORMSOURCE;
1467         nt_devmode->printquality     = 0x0258;
1468         nt_devmode->color            = COLOR_MONOCHROME;
1469         nt_devmode->duplex           = DUP_SIMPLEX;
1470         nt_devmode->yresolution      = 0;
1471         nt_devmode->ttoption         = TT_SUBDEV;
1472         nt_devmode->collate          = COLLATE_FALSE;
1473         nt_devmode->icmmethod        = 0;
1474         nt_devmode->icmintent        = 0;
1475         nt_devmode->mediatype        = 0;
1476         nt_devmode->dithertype       = 0;
1477
1478         /* non utilisés par un driver d'imprimante */
1479         nt_devmode->logpixels        = 0;
1480         nt_devmode->bitsperpel       = 0;
1481         nt_devmode->pelswidth        = 0;
1482         nt_devmode->pelsheight       = 0;
1483         nt_devmode->displayflags     = 0;
1484         nt_devmode->displayfrequency = 0;
1485         nt_devmode->reserved1        = 0;
1486         nt_devmode->reserved2        = 0;
1487         nt_devmode->panningwidth     = 0;
1488         nt_devmode->panningheight    = 0;
1489         
1490         nt_devmode->private=NULL;
1491 }
1492
1493
1494 /* error code:
1495         0: everything OK
1496         1: level not implemented
1497         2: file doesn't exist
1498         3: can't allocate memory
1499         4: can't free memory
1500         5: non existant struct
1501 */
1502
1503 /*
1504         A printer and a printer driver are 2 different things.
1505         NT manages them separatelly, Samba does the same.
1506         Why ? Simply because it's easier and it makes sense !
1507         
1508         Now explanation: You have 3 printers behind your samba server,
1509         2 of them are the same make and model (laser A and B). But laser B 
1510         has an 3000 sheet feeder and laser A doesn't such an option.
1511         Your third printer is an old dot-matrix model for the accounting :-).
1512         
1513         If the /usr/local/samba/lib directory (default dir), you will have
1514         5 files to describe all of this.
1515         
1516         3 files for the printers (1 by printer):
1517                 NTprinter_laser A
1518                 NTprinter_laser B
1519                 NTprinter_accounting
1520         2 files for the drivers (1 for the laser and 1 for the dot matrix)
1521                 NTdriver_printer model X
1522                 NTdriver_printer model Y
1523
1524 jfm: I should use this comment for the text file to explain 
1525         same thing for the forms BTW.
1526         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1527
1528 */
1529
1530