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