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