Changing drivers using the properties page works - but only if getting/setting
[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
25 extern int DEBUGLEVEL;
26
27 static TDB_CONTEXT *tdb; /* used for driver files */
28
29 #define FORMS_PREFIX "FORMS/"
30 #define DRIVERS_PREFIX "DRIVERS/"
31 #define PRINTERS_PREFIX "PRINTERS/"
32
33 #define DATABASE_VERSION 1
34
35 /* we need to have a small set of default forms to support our
36    default printer */
37 static nt_forms_struct default_forms[] = {
38         {"Letter", 0x20, 0x34b5b, 0x44367, 0x0, 0x0, 0x34b5b, 0x44367},
39         {"A4", 0xb0, 0x3354f, 0x4884e, 0x0, 0x0, 0x3354f, 0x4884e}
40 };
41
42
43 /****************************************************************************
44 open the NT printing tdb
45 ****************************************************************************/
46 BOOL nt_printing_init(void)
47 {
48         static pid_t local_pid;
49
50         if (tdb && local_pid == sys_getpid()) return True;
51         tdb = tdb_open(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
52         if (!tdb) {
53                 DEBUG(0,("Failed to open nt drivers database\n"));
54                 return False;
55         }
56
57         local_pid = sys_getpid();
58
59         /* handle a Samba upgrade */
60         tdb_writelock(tdb);
61         if (tdb_fetch_int(tdb, "INFO/version") != DATABASE_VERSION) {
62                 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
63                 tdb_store_int(tdb, "INFO/version", DATABASE_VERSION);
64         }
65         tdb_writeunlock(tdb);
66
67         return True;
68 }
69
70   
71 /****************************************************************************
72 get a form struct list
73 ****************************************************************************/
74 int get_ntforms(nt_forms_struct **list)
75 {
76         TDB_DATA kbuf, newkey, dbuf;
77         nt_forms_struct form;
78         int ret;
79         int n = 0;
80
81         for (kbuf = tdb_firstkey(tdb); 
82              kbuf.dptr; 
83              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
84                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
85                 
86                 dbuf = tdb_fetch(tdb, kbuf);
87                 if (!dbuf.dptr) continue;
88
89                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
90                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddddddd",
91                                  &form.flag, &form.width, &form.length, &form.left,
92                                  &form.top, &form.right, &form.bottom);
93                 safe_free(dbuf.dptr);
94                 if (ret != dbuf.dsize) continue;
95
96                 *list = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
97                 (*list)[n] = form;
98                 n++;
99         }
100
101         /* we should never return a null forms list or NT gets unhappy */
102         if (n == 0) {
103                 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
104                 n = sizeof(default_forms) / sizeof(default_forms[0]);
105         }
106         
107
108         return n;
109 }
110
111 /****************************************************************************
112 write a form struct list
113 ****************************************************************************/
114 int write_ntforms(nt_forms_struct **list, int number)
115 {
116         pstring buf, key;
117         int len;
118         TDB_DATA kbuf,dbuf;
119         int i;
120
121         for (i=0;i<number;i++) {
122                 len = tdb_pack(buf, sizeof(buf), "ddddddd", 
123                                (*list)[i].flag, (*list)[i].width, (*list)[i].length,
124                                (*list)[i].left, (*list)[i].top, (*list)[i].right, 
125                                (*list)[i].bottom);
126                 if (len > sizeof(buf)) break;
127                 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[i].name);
128                 kbuf.dsize = strlen(key)+1;
129                 kbuf.dptr = key;
130                 dbuf.dsize = len;
131                 dbuf.dptr = buf;
132                 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
133        }
134
135        return i;
136 }
137
138 /****************************************************************************
139 add a form struct at the end of the list
140 ****************************************************************************/
141 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
142 {
143         int n=0;
144         BOOL update;
145         fstring form_name;
146
147         /* 
148          * NT tries to add forms even when 
149          * they are already in the base
150          * only update the values if already present
151          */
152
153         update=False;
154         
155         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
156         for (n=0; n<*count && update==False; n++)
157         {
158                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
159                 {
160                         DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
161                         update=True;
162                 }
163         }
164
165         if (update==False)
166         {
167                 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
168                         return False;
169                 unistr2_to_ascii((*list)[n].name, &(form->name), sizeof((*list)[n].name)-1);
170                 (*count)++;
171         }
172         
173         (*list)[n].flag=form->flags;
174         (*list)[n].width=form->size_x;
175         (*list)[n].length=form->size_y;
176         (*list)[n].left=form->left;
177         (*list)[n].top=form->top;
178         (*list)[n].right=form->right;
179         (*list)[n].bottom=form->bottom;
180
181         return True;
182 }
183
184 /****************************************************************************
185 update a form struct 
186 ****************************************************************************/
187 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
188 {
189         int n=0;
190         fstring form_name;
191         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
192
193         DEBUG(106, ("[%s]\n", form_name));
194         for (n=0; n<count; n++)
195         {
196                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
197                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
198                         break;
199         }
200
201         if (n==count) return;
202
203         (*list)[n].flag=form->flags;
204         (*list)[n].width=form->size_x;
205         (*list)[n].length=form->size_y;
206         (*list)[n].left=form->left;
207         (*list)[n].top=form->top;
208         (*list)[n].right=form->right;
209         (*list)[n].bottom=form->bottom;
210 }
211  
212 /****************************************************************************
213 get the nt drivers list
214
215 traverse the database and look-up the matching names
216 ****************************************************************************/
217 int get_ntdrivers(fstring **list, char *architecture)
218 {
219         int total=0;
220         fstring short_archi;
221         pstring key;
222         TDB_DATA kbuf, newkey;
223
224         get_short_archi(short_archi, architecture);
225         slprintf(key, sizeof(key), "%s%s/", DRIVERS_PREFIX, short_archi);
226
227         for (kbuf = tdb_firstkey(tdb); 
228              kbuf.dptr; 
229              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
230                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
231                 
232                 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
233                         return -1;
234
235                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
236                 total++;
237         }
238
239         return(total);
240 }
241
242 /****************************************************************************
243 function to do the mapping between the long architecture name and
244 the short one.
245 ****************************************************************************/
246 void get_short_archi(char *short_archi, char *long_archi)
247 {
248         struct table {
249                 char *long_archi;
250                 char *short_archi;
251         };
252         
253         struct table archi_table[]=
254         {
255                 {"Windows 4.0",          "WIN40"    },
256                 {"Windows NT x86",       "W32X86"   },
257                 {"Windows NT R4000",     "W32mips"  },
258                 {"Windows NT Alpha_AXP", "W32alpha" },
259                 {"Windows NT PowerPC",   "W32ppc"   },
260                 {NULL,                   ""         }
261         };
262         
263         int i=-1;
264
265         DEBUG(107,("Getting architecture dependant directory\n"));
266         do {
267                 i++;
268         } while ( (archi_table[i].long_archi!=NULL ) && strncmp(long_archi, archi_table[i].long_archi, strlen(long_archi)) );
269
270         if (archi_table[i].long_archi==NULL)
271         {
272                 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
273         }
274         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
275
276         DEBUGADD(108,("index: [%d]\n", i));
277         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
278         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
279 }
280
281 /****************************************************************************
282 ****************************************************************************/
283 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
284 {
285         int len, buflen;
286         fstring architecture;
287         pstring key;
288         char *buf;
289         int i, ret;
290         TDB_DATA kbuf, dbuf;
291
292         get_short_archi(architecture, driver->environment);
293         slprintf(key, sizeof(key), "%s%s/%s", DRIVERS_PREFIX, architecture, driver->name);
294
295         /*
296          * cversion must be 2.
297          * when adding a printer ON the SERVER
298          * rpcAddPrinterDriver defines it to zero
299          * which is wrong !!!
300          *
301          * JFM, 4/14/99
302          */
303         driver->cversion=2;
304         
305         buf = NULL;
306         len = buflen = 0;
307
308  again:
309         len = 0;
310         len += tdb_pack(buf+len, buflen-len, "dffffffff", 
311                         driver->cversion,
312                         driver->name,
313                         driver->environment,
314                         driver->driverpath,
315                         driver->datafile,
316                         driver->configfile,
317                         driver->helpfile,
318                         driver->monitorname,
319                         driver->defaultdatatype);
320         
321         if (driver->dependentfiles) {
322                 for (i=0; *driver->dependentfiles[i]; i++) {
323                         len += tdb_pack(buf+len, buflen-len, "f", 
324                                         driver->dependentfiles[i]);
325                 }
326         }
327
328         if (len != buflen) {
329                 buf = (char *)Realloc(buf, len);
330                 buflen = len;
331                 goto again;
332         }
333
334
335         kbuf.dptr = key;
336         kbuf.dsize = strlen(key)+1;
337         dbuf.dptr = buf;
338         dbuf.dsize = len;
339         
340         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
341
342         safe_free(buf);
343         return ret;
344 }
345
346 /****************************************************************************
347 ****************************************************************************/
348 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
349 {
350         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
351
352         ZERO_STRUCT(info3);
353         info3.cversion = driver->version;
354         fstrcpy(info3.environment,driver->environment);
355         fstrcpy(info3.driverpath,driver->driverpath);
356         fstrcpy(info3.datafile,driver->datafile);
357         fstrcpy(info3.configfile,driver->configfile);
358         fstrcpy(info3.helpfile,driver->helpfile);
359         fstrcpy(info3.monitorname,driver->monitorname);
360         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
361         info3.dependentfiles = driver->dependentfiles;
362
363         return add_a_printer_driver_3(&info3);
364 }
365
366
367 /****************************************************************************
368 ****************************************************************************/
369 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
370 {
371         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
372         int snum;
373
374         ZERO_STRUCT(info);
375
376         snum = lp_servicenumber(in_prt);
377
378         fstrcpy(info.name, lp_printerdriver(snum));
379         fstrcpy(info.defaultdatatype, "RAW");
380         
381         fstrcpy(info.driverpath, "");
382         fstrcpy(info.datafile, "");
383         fstrcpy(info.configfile, "");
384         fstrcpy(info.helpfile, "");
385
386         if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
387                 return ERROR_NOT_ENOUGH_MEMORY;
388
389         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
390         fstrcpy(info.dependentfiles[0], "");
391
392         *info_ptr = memdup(&info, sizeof(info));
393         
394         return 0;       
395 }
396
397 /****************************************************************************
398 ****************************************************************************/
399 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
400 {
401         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
402         TDB_DATA kbuf, dbuf;
403         fstring architecture;
404         int len = 0;
405         int i;
406         pstring key;
407
408         ZERO_STRUCT(driver);
409
410         get_short_archi(architecture, in_arch);
411         slprintf(key, sizeof(key), "%s%s/%s", DRIVERS_PREFIX, architecture, in_prt);
412
413         kbuf.dptr = key;
414         kbuf.dsize = strlen(key)+1;
415         
416         dbuf = tdb_fetch(tdb, kbuf);
417         if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
418
419         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff", 
420                           &driver.cversion,
421                           driver.name,
422                           driver.environment,
423                           driver.driverpath,
424                           driver.datafile,
425                           driver.configfile,
426                           driver.helpfile,
427                           driver.monitorname,
428                           driver.defaultdatatype);
429
430         i=0;
431         while (len < dbuf.dsize) {
432                 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
433                                                          sizeof(fstring)*(i+2));
434                 if (driver.dependentfiles == NULL)
435                         break;
436
437                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", 
438                                   &driver.dependentfiles[i]);
439                 i++;
440         }
441         if (driver.dependentfiles != NULL)
442                 fstrcpy(driver.dependentfiles[i], "");
443
444         safe_free(dbuf.dptr);
445
446         if (len != dbuf.dsize) {
447                 if (driver.dependentfiles != NULL)
448                         safe_free(driver.dependentfiles);
449
450                 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
451         }
452
453         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
454
455         return 0;
456 }
457
458 /****************************************************************************
459 debugging function, dump at level 6 the struct in the logs
460 ****************************************************************************/
461 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
462 {
463         uint32 success;
464         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
465         int i;
466         
467         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
468         
469         switch (level)
470         {
471                 case 3: 
472                 {
473                         if (driver.info_3 == NULL)
474                                 success=5;
475                         else {
476                                 info3=driver.info_3;
477                         
478                                 DEBUGADD(106,("version:[%d]\n",         info3->cversion));
479                                 DEBUGADD(106,("name:[%s]\n",            info3->name));
480                                 DEBUGADD(106,("environment:[%s]\n",     info3->environment));
481                                 DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
482                                 DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
483                                 DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
484                                 DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
485                                 DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
486                                 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
487                                 
488                                 for (i=0; info3->dependentfiles &&
489                                           *info3->dependentfiles[i]; i++) {
490                                         DEBUGADD(106,("dependentfile:[%s]\n", 
491                                                       info3->dependentfiles[i]));
492                                 }
493                                 success=0;
494                         }
495                         break;
496                 }
497                 default:
498                         DEBUGADD(1,("Level not implemented\n"));
499                         success=1;
500                         break;
501         }
502         
503         return (success);
504 }
505
506 /****************************************************************************
507 ****************************************************************************/
508 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
509 {
510         int len = 0;
511
512         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
513
514         if (!nt_devmode) return len;
515
516         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
517                         nt_devmode->devicename,
518                         nt_devmode->formname,
519
520                         nt_devmode->specversion,
521                         nt_devmode->driverversion,
522                         nt_devmode->size,
523                         nt_devmode->driverextra,
524                         nt_devmode->orientation,
525                         nt_devmode->papersize,
526                         nt_devmode->paperlength,
527                         nt_devmode->paperwidth,
528                         nt_devmode->scale,
529                         nt_devmode->copies,
530                         nt_devmode->defaultsource,
531                         nt_devmode->printquality,
532                         nt_devmode->color,
533                         nt_devmode->duplex,
534                         nt_devmode->yresolution,
535                         nt_devmode->ttoption,
536                         nt_devmode->collate,
537                         nt_devmode->logpixels,
538                         
539                         nt_devmode->fields,
540                         nt_devmode->bitsperpel,
541                         nt_devmode->pelswidth,
542                         nt_devmode->pelsheight,
543                         nt_devmode->displayflags,
544                         nt_devmode->displayfrequency,
545                         nt_devmode->icmmethod,
546                         nt_devmode->icmintent,
547                         nt_devmode->mediatype,
548                         nt_devmode->dithertype,
549                         nt_devmode->reserved1,
550                         nt_devmode->reserved2,
551                         nt_devmode->panningwidth,
552                         nt_devmode->panningheight,
553                         nt_devmode->private);
554
555         
556         if (nt_devmode->private) {
557                 len += tdb_pack(buf+len, buflen-len, "B",
558                                 nt_devmode->driverextra,
559                                 nt_devmode->private);
560         }
561
562         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
563
564         return len;
565 }
566
567 /****************************************************************************
568 ****************************************************************************/
569 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
570 {
571         int len = 0;
572
573         while (param != NULL) {
574                 len += tdb_pack(buf+len, buflen-len, "pfdB",
575                                 param,
576                                 param->value, 
577                                 param->type, 
578                                 param->data_len,
579                                 param->data);
580                 param=param->next;      
581         }
582
583         len += tdb_pack(buf+len, buflen-len, "p", param);
584
585         return len;
586 }
587
588
589 /****************************************************************************
590 delete a printer - this just deletes the printer info file, any open
591 handles are not affected
592 ****************************************************************************/
593 uint32 del_a_printer(char *portname)
594 {
595         pstring key;
596         TDB_DATA kbuf;
597
598         slprintf(key, sizeof(key), "%s%s",
599                  PRINTERS_PREFIX, portname);
600
601         kbuf.dptr=key;
602         kbuf.dsize=strlen(key)+1;
603
604         tdb_delete(tdb, kbuf);
605         return 0;
606 }
607
608 /****************************************************************************
609 ****************************************************************************/
610 static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
611 {
612         pstring key;
613         char *buf;
614         int buflen, len, ret;
615         TDB_DATA kbuf, dbuf;
616         
617         /* 
618          * in addprinter: no servername and the printer is the name
619          * in setprinter: servername is \\server
620          *                and printer is \\server\\printer
621          *
622          * Samba manages only local printers.
623          * we currently don't support things like path=\\other_server\printer
624          */
625         if (info->servername[0]!='\0')
626         {
627                 trim_string(info->printername, info->servername, NULL);
628                 trim_string(info->printername, "\\", NULL);
629                 info->servername[0]='\0';
630         }
631
632         /*
633          * JFM: one day I'll forget.
634          * below that's info->portname because that's the SAMBA sharename
635          * and I made NT 'thinks' it's the portname
636          * the info->sharename is the thing you can name when you add a printer
637          * that's the short-name when you create shared printer for 95/98
638          * So I've made a limitation in SAMBA: you can only have 1 printer model
639          * behind a SAMBA share.
640          */
641
642
643         buf = NULL;
644         buflen = 0;
645
646  again: 
647         len = 0;
648         len += tdb_pack(buf+len, buflen-len, "dddddddddddffffffffff",
649                         info->attributes,
650                         info->priority,
651                         info->default_priority,
652                         info->starttime,
653                         info->untiltime,
654                         info->status,
655                         info->cjobs,
656                         info->averageppm,
657                         info->changeid,
658                         info->c_setprinter,
659                         info->setuptime,
660                         info->servername,
661                         info->printername,
662                         info->sharename,
663                         info->portname,
664                         info->drivername,
665                         info->location,
666                         info->sepfile,
667                         info->printprocessor,
668                         info->datatype,
669                         info->parameters);
670
671         len += pack_devicemode(info->devmode, buf+len, buflen-len);
672         len += pack_specifics(info->specific, buf+len, buflen-len);
673
674         if (buflen != len) {
675                 buf = (char *)Realloc(buf, len);
676                 buflen = len;
677                 goto again;
678         }
679         
680
681         slprintf(key, sizeof(key), "%s%s",
682                  PRINTERS_PREFIX, info->portname);
683
684         kbuf.dptr = key;
685         kbuf.dsize = strlen(key)+1;
686         dbuf.dptr = buf;
687         dbuf.dsize = len;
688
689         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
690
691         safe_free(buf);
692
693         DEBUG(8,("packed printer [%s] with printprocessor [%s] parameters=[%s] len=%d\n", 
694                  info->portname, info->printprocessor, info->parameters, len));
695
696         return ret;
697 }
698
699
700 /****************************************************************************
701 ****************************************************************************/
702 BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
703 {
704         NT_PRINTER_PARAM *current;
705         
706         DEBUG(108,("add_a_specific_param\n"));  
707
708         param->next=NULL;
709         
710         if (info_2->specific == NULL)
711         {
712                 info_2->specific=param;
713         }
714         else
715         {
716                 current=info_2->specific;               
717                 while (current->next != NULL) {
718                         current=current->next;
719                 }               
720                 current->next=param;
721         }
722         return (True);
723 }
724
725 /****************************************************************************
726 ****************************************************************************/
727 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
728 {
729         NT_PRINTER_PARAM *current;
730         NT_PRINTER_PARAM *previous;
731         
732         current=info_2->specific;
733         previous=current;
734         
735         if (current==NULL) return (False);
736         
737         if ( !strcmp(current->value, param->value) && 
738             (strlen(current->value)==strlen(param->value)) ) {
739                 DEBUG(109,("deleting first value\n"));
740                 info_2->specific=current->next;
741                 safe_free(current->data);
742                 safe_free(current);
743                 DEBUG(109,("deleted first value\n"));
744                 return (True);
745         }
746
747         current=previous->next;
748                 
749         while ( current!=NULL ) {
750                 if (!strcmp(current->value, param->value) &&
751                     strlen(current->value)==strlen(param->value) ) {
752                         DEBUG(109,("deleting current value\n"));
753                         previous->next=current->next;
754                         safe_free(current->data);
755                         safe_free(current);
756                         DEBUG(109,("deleted current value\n"));
757                         return(True);
758                 }
759                 
760                 previous=previous->next;
761                 current=current->next;
762         }
763         return (False);
764 }
765
766 /****************************************************************************
767  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
768 ****************************************************************************/
769 static void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
770 {
771         NT_PRINTER_PARAM *param = *param_ptr;
772
773         if(param == NULL)
774                 return;
775
776         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
777
778         if(param->data)
779                 safe_free(param->data);
780
781         safe_free(param);
782         *param_ptr = NULL;
783 }
784
785 /****************************************************************************
786  Malloc and return an NT devicemode.
787 ****************************************************************************/
788
789 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
790 {
791 /*
792  * should I init this ones ???
793         nt_devmode->devicename
794 */
795
796         NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
797
798         if (nt_devmode == NULL) {
799                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
800                 return NULL;
801         }
802
803         ZERO_STRUCTP(nt_devmode);
804
805         fstrcpy(nt_devmode->devicename, default_devicename);
806         fstrcpy(nt_devmode->formname, "Letter");
807
808         nt_devmode->specversion      = 0x0401;
809         nt_devmode->driverversion    = 0x0400;
810         nt_devmode->size             = 0x00DC;
811         nt_devmode->driverextra      = 0x0000;
812         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY | 
813                                        DEFAULTSOURCE | COPIES | SCALE | 
814                                        PAPERSIZE | ORIENTATION;
815         nt_devmode->orientation      = 1;
816         nt_devmode->papersize        = PAPER_LETTER;
817         nt_devmode->paperlength      = 0;
818         nt_devmode->paperwidth       = 0;
819         nt_devmode->scale            = 0x64;
820         nt_devmode->copies           = 01;
821         nt_devmode->defaultsource    = BIN_FORMSOURCE;
822         nt_devmode->printquality     = 0x0258;
823         nt_devmode->color            = COLOR_MONOCHROME;
824         nt_devmode->duplex           = DUP_SIMPLEX;
825         nt_devmode->yresolution      = 0;
826         nt_devmode->ttoption         = TT_SUBDEV;
827         nt_devmode->collate          = COLLATE_FALSE;
828         nt_devmode->icmmethod        = 0;
829         nt_devmode->icmintent        = 0;
830         nt_devmode->mediatype        = 0;
831         nt_devmode->dithertype       = 0;
832
833         /* non utilisés par un driver d'imprimante */
834         nt_devmode->logpixels        = 0;
835         nt_devmode->bitsperpel       = 0;
836         nt_devmode->pelswidth        = 0;
837         nt_devmode->pelsheight       = 0;
838         nt_devmode->displayflags     = 0;
839         nt_devmode->displayfrequency = 0;
840         nt_devmode->reserved1        = 0;
841         nt_devmode->reserved2        = 0;
842         nt_devmode->panningwidth     = 0;
843         nt_devmode->panningheight    = 0;
844         
845         nt_devmode->private=NULL;
846
847         return nt_devmode;
848 }
849
850 /****************************************************************************
851  Deepcopy an NT devicemode.
852 ****************************************************************************/
853
854 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
855 {
856         NT_DEVICEMODE *new_nt_devicemode = NULL;
857
858         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
859                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
860                 return NULL;
861         }
862
863         new_nt_devicemode->private = NULL;
864         if (nt_devicemode->private != NULL) {
865                 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
866                         safe_free(new_nt_devicemode);
867                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
868                         return NULL;
869         }
870         }
871
872         return new_nt_devicemode;
873 }
874
875 /****************************************************************************
876  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
877 ****************************************************************************/
878
879 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
880 {
881         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
882
883         if(nt_devmode == NULL)
884                 return;
885
886         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
887
888         if(nt_devmode->private)
889                 safe_free(nt_devmode->private);
890
891         safe_free(nt_devmode);
892         *devmode_ptr = NULL;
893 }
894
895 /****************************************************************************
896  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
897 ****************************************************************************/
898 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
899 {
900         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
901         NT_PRINTER_PARAM *param_ptr;
902
903         if(info == NULL)
904                 return;
905
906         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
907
908         free_nt_devicemode(&info->devmode);
909         free_sec_desc_buf(&info->secdesc_buf);
910
911         for(param_ptr = info->specific; param_ptr; ) {
912                 NT_PRINTER_PARAM *tofree = param_ptr;
913
914                 param_ptr = param_ptr->next;
915                 free_nt_printer_param(&tofree);
916         }
917
918         safe_free(*info_ptr);
919         *info_ptr = NULL;
920 }
921
922
923 /****************************************************************************
924 ****************************************************************************/
925 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
926 {
927         int len = 0;
928         NT_DEVICEMODE devmode;
929
930         ZERO_STRUCT(devmode);
931
932         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
933
934         if (!*nt_devmode) return len;
935
936         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
937                           devmode.devicename,
938                           devmode.formname,
939
940                           &devmode.specversion,
941                           &devmode.driverversion,
942                           &devmode.size,
943                           &devmode.driverextra,
944                           &devmode.orientation,
945                           &devmode.papersize,
946                           &devmode.paperlength,
947                           &devmode.paperwidth,
948                           &devmode.scale,
949                           &devmode.copies,
950                           &devmode.defaultsource,
951                           &devmode.printquality,
952                           &devmode.color,
953                           &devmode.duplex,
954                           &devmode.yresolution,
955                           &devmode.ttoption,
956                           &devmode.collate,
957                           &devmode.logpixels,
958                           
959                           &devmode.fields,
960                           &devmode.bitsperpel,
961                           &devmode.pelswidth,
962                           &devmode.pelsheight,
963                           &devmode.displayflags,
964                           &devmode.displayfrequency,
965                           &devmode.icmmethod,
966                           &devmode.icmintent,
967                           &devmode.mediatype,
968                           &devmode.dithertype,
969                           &devmode.reserved1,
970                           &devmode.reserved2,
971                           &devmode.panningwidth,
972                           &devmode.panningheight,
973                           &devmode.private);
974         
975         if (devmode.private) {
976                 devmode.private = (uint8 *)malloc(devmode.driverextra);
977                 if (!devmode.private) return 2;
978                 len += tdb_unpack(buf+len, buflen-len, "B",
979                                   devmode.driverextra,
980                                   devmode.private);
981         }
982
983         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
984
985         DEBUG(8,("Unpacked devicemode [%s]\n", devmode.formname));
986
987         return len;
988 }
989
990 /****************************************************************************
991 ****************************************************************************/
992 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
993 {
994         int len = 0;
995         NT_PRINTER_PARAM param, *p;
996
997         *list = NULL;
998
999         while (1) {
1000                 len += tdb_unpack(buf+len, buflen-len, "p", &p);
1001                 if (!p) break;
1002
1003                 len += tdb_unpack(buf+len, buflen-len, "fdB",
1004                                   param.value, 
1005                                   &param.type, 
1006                                   &param.data_len,
1007                                   &param.data);
1008                 param.next = *list;
1009                 *list = memdup(&param, sizeof(param));
1010         }
1011
1012         return len;
1013 }
1014
1015
1016 /****************************************************************************
1017 get a default printer info 2 struct
1018 ****************************************************************************/
1019 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1020 {
1021         extern pstring global_myname;
1022         int snum;
1023         NT_PRINTER_INFO_LEVEL_2 info;
1024
1025         ZERO_STRUCT(info);
1026
1027         snum = lp_servicenumber(sharename);
1028
1029         fstrcpy(info.servername, global_myname);
1030         fstrcpy(info.printername, sharename);
1031         fstrcpy(info.portname, sharename);
1032         fstrcpy(info.drivername, lp_printerdriver(snum));
1033         fstrcpy(info.printprocessor, "winprint");
1034         fstrcpy(info.datatype, "RAW");
1035
1036         info.attributes = PRINTER_ATTRIBUTE_SHARED   \
1037                          | PRINTER_ATTRIBUTE_LOCAL  \
1038                          | PRINTER_ATTRIBUTE_RAW_ONLY ;            /* attributes */
1039
1040         info.starttime = 0; /* Minutes since 12:00am GMT */
1041         info.untiltime = 0; /* Minutes since 12:00am GMT */
1042
1043         if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
1044                 goto fail;
1045
1046         if (!nt_printing_getsec(sharename, &info.secdesc_buf))
1047                 goto fail;
1048
1049         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
1050         if (! *info_ptr) {
1051                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
1052                 goto fail;
1053         }
1054
1055         return (0);     
1056
1057   fail:
1058
1059         if (info.devmode)
1060                 free_nt_devicemode(&info.devmode);
1061         if (info.secdesc_buf)
1062                 free_sec_desc_buf(&info.secdesc_buf);
1063         return 2;
1064 }
1065
1066 /****************************************************************************
1067 ****************************************************************************/
1068 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1069 {
1070         pstring key;
1071         NT_PRINTER_INFO_LEVEL_2 info;
1072         int len = 0;
1073         TDB_DATA kbuf, dbuf;
1074                 
1075         ZERO_STRUCT(info);
1076
1077         slprintf(key, sizeof(key), "%s%s",
1078                  PRINTERS_PREFIX, sharename);
1079
1080         kbuf.dptr = key;
1081         kbuf.dsize = strlen(key)+1;
1082
1083         dbuf = tdb_fetch(tdb, kbuf);
1084 #if 1 /* JRATEST */
1085         if (!dbuf.dptr) return get_a_printer_2_default(info_ptr, sharename);
1086 #else
1087         if (!dbuf.dptr) return 1;
1088 #endif
1089
1090         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddffffffffff",
1091                         &info.attributes,
1092                         &info.priority,
1093                         &info.default_priority,
1094                         &info.starttime,
1095                         &info.untiltime,
1096                         &info.status,
1097                         &info.cjobs,
1098                         &info.averageppm,
1099                         &info.changeid,
1100                         &info.c_setprinter,
1101                         &info.setuptime,
1102                         info.servername,
1103                         info.printername,
1104                         info.sharename,
1105                         info.portname,
1106                         info.drivername,
1107                         info.location,
1108                         info.sepfile,
1109                         info.printprocessor,
1110                         info.datatype,
1111                         info.parameters);
1112
1113         info.attributes |= PRINTER_ATTRIBUTE_RAW_ONLY; /* Samba has to have raw drivers. */
1114
1115         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
1116         len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
1117
1118 #if 0 /* JRATEST */
1119         nt_printing_getsec(sharename, &info.secdesc_buf);
1120 #endif /* JRATEST */
1121
1122         fstrcpy(info.sharename, "");
1123
1124         safe_free(dbuf.dptr);
1125         *info_ptr=memdup(&info, sizeof(info));
1126
1127         DEBUG(9,("Unpacked printprocessor for [%s] of [%s]\n",
1128                  sharename, info.printprocessor));
1129
1130         
1131         return 0;       
1132 }
1133
1134 /****************************************************************************
1135 debugging function, dump at level 6 the struct in the logs
1136 ****************************************************************************/
1137 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1138 {
1139         uint32 success;
1140         NT_PRINTER_INFO_LEVEL_2 *info2;
1141         
1142         DEBUG(106,("Dumping printer at level [%d]\n", level));
1143         
1144         switch (level)
1145         {
1146                 case 2: 
1147                 {
1148                         if (printer.info_2 == NULL)
1149                                 success=5;
1150                         else
1151                         {
1152                                 info2=printer.info_2;
1153                         
1154                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
1155                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
1156                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
1157                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
1158                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
1159                                 DEBUGADD(106,("status:[%d]\n", info2->status));
1160                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
1161                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
1162                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
1163                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
1164                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
1165
1166                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
1167                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
1168                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
1169                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
1170                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
1171                                 DEBUGADD(106,("location:[%s]\n", info2->location));
1172                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
1173                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
1174                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
1175                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
1176                                 success=0;
1177                         }
1178                         break;
1179                 }
1180                 default:
1181                         DEBUGADD(1,("Level not implemented\n"));
1182                         success=1;
1183                         break;
1184         }
1185         
1186         return (success);
1187 }
1188
1189 /*
1190  * The function below are the high level ones.
1191  * only those ones must be called from the spoolss code.
1192  * JFM.
1193  */
1194
1195
1196 /****************************************************************************
1197 ****************************************************************************/
1198 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1199 {
1200         uint32 success;
1201         
1202         dump_a_printer(printer, level); 
1203         
1204         switch (level)
1205         {
1206                 case 2: 
1207                 {
1208                         success=add_a_printer_2(printer.info_2);
1209                         break;
1210                 }
1211                 default:
1212                         success=1;
1213                         break;
1214         }
1215         
1216         return (success);
1217 }
1218
1219 /****************************************************************************
1220  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
1221 ****************************************************************************/
1222
1223 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
1224 {
1225         uint32 success;
1226         NT_PRINTER_INFO_LEVEL *printer = NULL;
1227         
1228         *pp_printer = NULL;
1229
1230         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
1231
1232         switch (level)
1233         {
1234                 case 2: 
1235                 {
1236                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
1237                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
1238                                 return 1;
1239                         }
1240                         ZERO_STRUCTP(printer);
1241                         success=get_a_printer_2(&printer->info_2, sharename);
1242                         if (success == 0) {
1243                                 dump_a_printer(*printer, level);
1244                                 *pp_printer = printer;
1245                         } else {
1246                                 safe_free(printer);
1247                         }
1248                         break;
1249                 }
1250                 default:
1251                         success=1;
1252                         break;
1253         }
1254         
1255         DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
1256
1257         return (success);
1258 }
1259
1260 /****************************************************************************
1261  Deletes a NT_PRINTER_INFO_LEVEL struct.
1262 ****************************************************************************/
1263
1264 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
1265 {
1266         uint32 success;
1267         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
1268
1269         DEBUG(104,("freeing a printer at level [%d]\n", level));
1270
1271         if (printer == NULL)
1272                 return 0;
1273         
1274         switch (level)
1275         {
1276                 case 2: 
1277                 {
1278                         if (printer->info_2 != NULL)
1279                         {
1280                                 free_nt_printer_info_level_2(&printer->info_2);
1281                                 success=0;
1282                         }
1283                         else
1284                         {
1285                                 success=4;
1286                         }
1287                         break;
1288                 }
1289                 default:
1290                         success=1;
1291                         break;
1292         }
1293
1294         safe_free(printer);
1295         *pp_printer = NULL;
1296         return (success);
1297 }
1298
1299 /****************************************************************************
1300 ****************************************************************************/
1301 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1302 {
1303         uint32 success;
1304         DEBUG(104,("adding a printer at level [%d]\n", level));
1305         dump_a_printer_driver(driver, level);
1306         
1307         switch (level)
1308         {
1309                 case 3: 
1310                 {
1311                         success=add_a_printer_driver_3(driver.info_3);
1312                         break;
1313                 }
1314
1315                 case 6: 
1316                 {
1317                         success=add_a_printer_driver_6(driver.info_6);
1318                         break;
1319                 }
1320                 default:
1321                         success=1;
1322                         break;
1323         }
1324         
1325         return (success);
1326 }
1327 /****************************************************************************
1328 ****************************************************************************/
1329 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, 
1330                             fstring printername, fstring architecture)
1331 {
1332         uint32 success;
1333         
1334         switch (level)
1335         {
1336                 case 3: 
1337                 {
1338                         success=get_a_printer_driver_3(&(driver->info_3), 
1339                                                        printername,
1340                                                        architecture);
1341                         break;
1342                 }
1343                 default:
1344                         success=1;
1345                         break;
1346         }
1347         
1348         if (success == 0) dump_a_printer_driver(*driver, level);
1349         return (success);
1350 }
1351
1352 /****************************************************************************
1353 ****************************************************************************/
1354 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1355 {
1356         uint32 success;
1357         
1358         switch (level)
1359         {
1360                 case 3: 
1361                 {
1362                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1363                         if (driver.info_3 != NULL)
1364                         {
1365                                 info3=driver.info_3;
1366                                 safe_free(info3->dependentfiles);
1367                                 ZERO_STRUCTP(info3);
1368                                 safe_free(info3);
1369                                 success=0;
1370                         }
1371                         else
1372                         {
1373                                 success=4;
1374                         }
1375                         break;
1376                 }
1377                 case 6: 
1378                 {
1379                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
1380                         if (driver.info_6 != NULL)
1381                         {
1382                                 info6=driver.info_6;
1383                                 safe_free(info6->dependentfiles);
1384                                 safe_free(info6->previousnames);
1385                                 ZERO_STRUCTP(info6);
1386                                 safe_free(info6);
1387                                 success=0;
1388                         }
1389                         else
1390                         {
1391                                 success=4;
1392                         }
1393                         break;
1394                 }
1395                 default:
1396                         success=1;
1397                         break;
1398         }
1399         return (success);
1400 }
1401
1402 /****************************************************************************
1403 ****************************************************************************/
1404 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
1405                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
1406 {
1407         /* right now that's enough ! */ 
1408         NT_PRINTER_PARAM *param;
1409         int i=0;
1410         
1411         param=printer.info_2->specific;
1412         
1413         while (param != NULL && i <= param_index)
1414         {
1415                 param=param->next;
1416                 i++;
1417         }
1418         
1419         if (param == NULL)
1420                 return False;
1421
1422         /* exited because it exist */
1423         *type=param->type;              
1424         StrnCpy(value, param->value, sizeof(fstring)-1);
1425         *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1426         if(*data == NULL)
1427                 return False;
1428         memcpy(*data, param->data, param->data_len);
1429         *len=param->data_len;
1430         return True;
1431 }
1432
1433 /****************************************************************************
1434 ****************************************************************************/
1435 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, 
1436                         fstring value, uint8 **data, uint32 *type, uint32 *len)
1437 {
1438         /* right now that's enough ! */ 
1439         NT_PRINTER_PARAM *param;
1440         
1441         DEBUG(105, ("get_specific_param\n"));
1442         
1443         param=printer.info_2->specific;
1444                 
1445         while (param != NULL)
1446         {
1447                 if ( !strcmp(value, param->value) 
1448                     && strlen(value)==strlen(param->value))
1449                         break;
1450                         
1451                 param=param->next;
1452         }
1453         
1454         DEBUG(106, ("found one param\n"));
1455         if (param != NULL)
1456         {
1457                 /* exited because it exist */
1458                 *type=param->type;      
1459                 
1460                 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1461                 if(*data == NULL)
1462                         return False;
1463                 memcpy(*data, param->data, param->data_len);
1464                 *len=param->data_len;
1465
1466                 DEBUG(106, ("exit of get_specific_param:true\n"));
1467                 return (True);
1468         }
1469         DEBUG(106, ("exit of get_specific_param:false\n"));
1470         return (False);
1471 }
1472
1473
1474 /****************************************************************************
1475 store a security desc for a printer
1476 ****************************************************************************/
1477 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
1478 {
1479         prs_struct ps;
1480         fstring key;
1481         uint32 status;
1482
1483         prs_init(&ps, (uint32)sec_desc_size(secdesc_ctr->sec) + sizeof(SEC_DESC_BUF), 4, MARSHALL);
1484
1485         if (!sec_io_desc_buf("nt_printing_setsec", &secdesc_ctr, &ps, 1)) {
1486                 status = ERROR_INVALID_FUNCTION;
1487                 goto out;
1488         }
1489
1490         slprintf(key, sizeof(key), "SECDESC/%s", printername);
1491
1492         if (tdb_prs_store(tdb, key, &ps)==0) {
1493                 status = 0;
1494         } else {
1495                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
1496                 status = ERROR_INVALID_FUNCTION;
1497         }
1498
1499  out:
1500         prs_mem_free(&ps);
1501         return status;
1502 }
1503
1504 /****************************************************************************
1505  Construct a default security descriptor buffer for a printer.
1506 ****************************************************************************/
1507
1508 static SEC_DESC_BUF *construct_default_printer_sdb(void)
1509 {
1510         extern DOM_SID global_sid_World; 
1511         SEC_ACE ace[2];
1512         SEC_ACCESS sa;
1513         SEC_ACL *psa = NULL;
1514         SEC_DESC_BUF *sdb = NULL;
1515         SEC_DESC *psd = NULL;
1516         size_t sd_size;
1517
1518         init_sec_access(&sa,PRINTER_MANAGE_DOCUMENTS);
1519         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1520                                         sa, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY);
1521         init_sec_ace(&ace[1], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1522                                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1523
1524         if ((psa = make_sec_acl( ACL_REVISION, 2, ace)) != NULL) {
1525                 psd = make_sec_desc(SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
1526                                                                         &global_sid_World, &global_sid_World, NULL, psa, &sd_size);
1527                 free_sec_acl(&psa);
1528         }
1529
1530         if (!psd) {
1531                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1532                 return NULL;
1533         }
1534
1535         sdb = make_sec_desc_buf(sd_size, psd);
1536
1537         DEBUG(4,("construct_default_printer_sdb: size = %u.\n", (unsigned int)sd_size));
1538
1539         free_sec_desc(&psd);
1540         return sdb;
1541 }
1542
1543 /****************************************************************************
1544  Get a security desc for a printer.
1545 ****************************************************************************/
1546
1547 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
1548 {
1549         prs_struct ps;
1550         fstring key;
1551
1552         slprintf(key, sizeof(key), "SECDESC/%s", printername);
1553
1554         if (tdb_prs_fetch(tdb, key, &ps)!=0 ||
1555             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
1556
1557                 DEBUG(4,("using default secdesc for %s\n", printername));
1558
1559                 if (!(*secdesc_ctr = construct_default_printer_sdb()))
1560                         return False;
1561
1562                 return True;
1563         }
1564
1565         prs_mem_free(&ps);
1566         return True;
1567 }
1568
1569 /* error code:
1570         0: everything OK
1571         1: level not implemented
1572         2: file doesn't exist
1573         3: can't allocate memory
1574         4: can't free memory
1575         5: non existant struct
1576 */
1577
1578 /*
1579         A printer and a printer driver are 2 different things.
1580         NT manages them separatelly, Samba does the same.
1581         Why ? Simply because it's easier and it makes sense !
1582         
1583         Now explanation: You have 3 printers behind your samba server,
1584         2 of them are the same make and model (laser A and B). But laser B 
1585         has an 3000 sheet feeder and laser A doesn't such an option.
1586         Your third printer is an old dot-matrix model for the accounting :-).
1587         
1588         If the /usr/local/samba/lib directory (default dir), you will have
1589         5 files to describe all of this.
1590         
1591         3 files for the printers (1 by printer):
1592                 NTprinter_laser A
1593                 NTprinter_laser B
1594                 NTprinter_accounting
1595         2 files for the drivers (1 for the laser and 1 for the dot matrix)
1596                 NTdriver_printer model X
1597                 NTdriver_printer model Y
1598
1599 jfm: I should use this comment for the text file to explain 
1600         same thing for the forms BTW.
1601         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1602
1603 */
1604
1605 static char *pace_str(uint32 ace_flags)
1606 {
1607         if ((ace_flags & PRINTER_ACE_FULL_CONTROL) == 
1608             PRINTER_ACE_FULL_CONTROL) return "full control";
1609
1610         if ((ace_flags & PRINTER_ACE_MANAGE_DOCUMENTS) ==
1611             PRINTER_ACE_MANAGE_DOCUMENTS) return "manage documents";
1612
1613         if ((ace_flags & PRINTER_ACE_PRINT) == PRINTER_ACE_PRINT)
1614                 return "print";
1615
1616         return "UNKNOWN";
1617 }
1618
1619 BOOL print_access_check(int snum, uint16 vuid, uint32 required_access)
1620 {
1621         SEC_DESC_BUF *secdesc = NULL;
1622         user_struct *user;
1623         char *p;
1624         int i;
1625
1626         /* Get printer name */
1627
1628         p = PRINTERNAME(snum);
1629         if (!p || !*p) p = SERVICE(snum);
1630
1631         /* Get printer security descriptor */
1632
1633         nt_printing_getsec(p, &secdesc);
1634         user = get_valid_user_struct(vuid);
1635
1636         /* Do something useful */
1637
1638         for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
1639                 DOM_SID *sid = &secdesc->sec->dacl->ace[i].sid;
1640                 uint32 ace_flags = secdesc->sec->dacl->ace[i].info.mask;
1641                 uint8 ace_type = secdesc->sec->dacl->ace[i].type;
1642                 fstring sid_str;
1643                 fstring dom_name, name;
1644                 uint8 name_type;
1645
1646                 sid_to_string(sid_str, sid);
1647                 winbind_lookup_sid(sid, dom_name, name, &name_type);
1648                 
1649                 DEBUG(0, ("ACE%d: %s/%s, %s%s\n", i, dom_name, name, 
1650                           (ace_type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? 
1651                           "+" : "-", pace_str(ace_flags)));
1652
1653                 DEBUG(0, ("\ttype = 0x%02x, flags = 0x%02x, size=0x%04x, mask=0x%08x\n", 
1654                           ace_type, secdesc->sec->dacl->ace[i].flags,
1655                           secdesc->sec->dacl->ace[i].size, ace_flags));
1656         }
1657
1658 #if 0
1659         /* Still mucking around with getting se_access_check() to work.
1660            Currently it takes a NET_USER_INFO_3 structure but this should
1661            perhaps be changed to a user_struct as it contains the
1662            user and group sid information required to perform the check. */
1663
1664         result = se_access_check(secdesc, user, required_access, 0,
1665                                  &acc_grant, &status);
1666 #endif
1667
1668         /* Free security descriptor */
1669
1670         free_sec_desc_buf(&secdesc);
1671
1672         return True;
1673 }