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