we are now sure the printer_info_2 timestamp is updated everytime
[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
374         ZERO_STRUCT(info);
375
376         fstrcpy(info.name, in_prt);
377         fstrcpy(info.defaultdatatype, "RAW");
378         
379         fstrcpy(info.driverpath, "");
380         fstrcpy(info.datafile, "");
381         fstrcpy(info.configfile, "");
382         fstrcpy(info.helpfile, "");
383
384         if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
385                 return ERROR_NOT_ENOUGH_MEMORY;
386
387         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
388         fstrcpy(info.dependentfiles[0], "");
389
390         *info_ptr = memdup(&info, sizeof(info));
391         
392         return 0;       
393 }
394
395 /****************************************************************************
396 ****************************************************************************/
397 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
398 {
399         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
400         TDB_DATA kbuf, dbuf;
401         fstring architecture;
402         int len = 0;
403         int i;
404         pstring key;
405
406         ZERO_STRUCT(driver);
407
408         get_short_archi(architecture, in_arch);
409         slprintf(key, sizeof(key), "%s%s/%s", DRIVERS_PREFIX, architecture, in_prt);
410
411         kbuf.dptr = key;
412         kbuf.dsize = strlen(key)+1;
413         
414         dbuf = tdb_fetch(tdb, kbuf);
415         if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
416
417         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff", 
418                           &driver.cversion,
419                           driver.name,
420                           driver.environment,
421                           driver.driverpath,
422                           driver.datafile,
423                           driver.configfile,
424                           driver.helpfile,
425                           driver.monitorname,
426                           driver.defaultdatatype);
427
428         i=0;
429         while (len < dbuf.dsize) {
430                 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
431                                                          sizeof(fstring)*(i+2));
432                 if (driver.dependentfiles == NULL)
433                         break;
434
435                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", 
436                                   &driver.dependentfiles[i]);
437                 i++;
438         }
439         if (driver.dependentfiles != NULL)
440                 fstrcpy(driver.dependentfiles[i], "");
441
442         safe_free(dbuf.dptr);
443
444         if (len != dbuf.dsize) {
445                 if (driver.dependentfiles != NULL)
446                         safe_free(driver.dependentfiles);
447
448                 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
449         }
450
451         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
452
453         return 0;
454 }
455
456 /****************************************************************************
457 debugging function, dump at level 6 the struct in the logs
458 ****************************************************************************/
459 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
460 {
461         uint32 success;
462         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
463         int i;
464         
465         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
466         
467         switch (level)
468         {
469                 case 3: 
470                 {
471                         if (driver.info_3 == NULL)
472                                 success=5;
473                         else {
474                                 info3=driver.info_3;
475                         
476                                 DEBUGADD(106,("version:[%d]\n",         info3->cversion));
477                                 DEBUGADD(106,("name:[%s]\n",            info3->name));
478                                 DEBUGADD(106,("environment:[%s]\n",     info3->environment));
479                                 DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
480                                 DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
481                                 DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
482                                 DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
483                                 DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
484                                 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
485                                 
486                                 for (i=0; info3->dependentfiles &&
487                                           *info3->dependentfiles[i]; i++) {
488                                         DEBUGADD(106,("dependentfile:[%s]\n", 
489                                                       info3->dependentfiles[i]));
490                                 }
491                                 success=0;
492                         }
493                         break;
494                 }
495                 default:
496                         DEBUGADD(1,("Level not implemented\n"));
497                         success=1;
498                         break;
499         }
500         
501         return (success);
502 }
503
504 /****************************************************************************
505 ****************************************************************************/
506 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
507 {
508         int len = 0;
509
510         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
511
512         if (!nt_devmode) return len;
513
514         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
515                         nt_devmode->devicename,
516                         nt_devmode->formname,
517
518                         nt_devmode->specversion,
519                         nt_devmode->driverversion,
520                         nt_devmode->size,
521                         nt_devmode->driverextra,
522                         nt_devmode->orientation,
523                         nt_devmode->papersize,
524                         nt_devmode->paperlength,
525                         nt_devmode->paperwidth,
526                         nt_devmode->scale,
527                         nt_devmode->copies,
528                         nt_devmode->defaultsource,
529                         nt_devmode->printquality,
530                         nt_devmode->color,
531                         nt_devmode->duplex,
532                         nt_devmode->yresolution,
533                         nt_devmode->ttoption,
534                         nt_devmode->collate,
535                         nt_devmode->logpixels,
536                         
537                         nt_devmode->fields,
538                         nt_devmode->bitsperpel,
539                         nt_devmode->pelswidth,
540                         nt_devmode->pelsheight,
541                         nt_devmode->displayflags,
542                         nt_devmode->displayfrequency,
543                         nt_devmode->icmmethod,
544                         nt_devmode->icmintent,
545                         nt_devmode->mediatype,
546                         nt_devmode->dithertype,
547                         nt_devmode->reserved1,
548                         nt_devmode->reserved2,
549                         nt_devmode->panningwidth,
550                         nt_devmode->panningheight,
551                         nt_devmode->private);
552
553         
554         if (nt_devmode->private) {
555                 len += tdb_pack(buf+len, buflen-len, "B",
556                                 nt_devmode->driverextra,
557                                 nt_devmode->private);
558         }
559
560         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
561
562         return len;
563 }
564
565 /****************************************************************************
566 ****************************************************************************/
567 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
568 {
569         int len = 0;
570
571         while (param != NULL) {
572                 len += tdb_pack(buf+len, buflen-len, "pfdB",
573                                 param,
574                                 param->value, 
575                                 param->type, 
576                                 param->data_len,
577                                 param->data);
578                 param=param->next;      
579         }
580
581         len += tdb_pack(buf+len, buflen-len, "p", param);
582
583         return len;
584 }
585
586
587 /****************************************************************************
588 delete a printer - this just deletes the printer info file, any open
589 handles are not affected
590 ****************************************************************************/
591 uint32 del_a_printer(char *portname)
592 {
593         pstring key;
594         TDB_DATA kbuf;
595
596         slprintf(key, sizeof(key), "%s%s",
597                  PRINTERS_PREFIX, portname);
598
599         kbuf.dptr=key;
600         kbuf.dsize=strlen(key)+1;
601
602         tdb_delete(tdb, kbuf);
603         return 0;
604 }
605
606 /****************************************************************************
607 ****************************************************************************/
608 static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
609 {
610         pstring key;
611         char *buf;
612         int buflen, len, ret;
613         TDB_DATA kbuf, dbuf;
614         NTTIME time_nt;
615         time_t time_unix;
616         
617         /* 
618          * in addprinter: no servername and the printer is the name
619          * in setprinter: servername is \\server
620          *                and printer is \\server\\printer
621          *
622          * Samba manages only local printers.
623          * we currently don't support things like path=\\other_server\printer
624          */
625         if (info->servername[0]!='\0')
626         {
627                 trim_string(info->printername, info->servername, NULL);
628                 trim_string(info->printername, "\\", NULL);
629                 info->servername[0]='\0';
630         }
631
632         /*
633          * JFM: one day I'll forget.
634          * below that's info->portname because that's the SAMBA sharename
635          * and I made NT 'thinks' it's the portname
636          * the info->sharename is the thing you can name when you add a printer
637          * that's the short-name when you create shared printer for 95/98
638          * So I've made a limitation in SAMBA: you can only have 1 printer model
639          * behind a SAMBA share.
640          */
641
642         unix_to_nt_time(&time_nt, time_unix);
643         info->changeid=time_nt.low;
644         info->c_setprinter++;
645
646         buf = NULL;
647         buflen = 0;
648
649  again: 
650         len = 0;
651         len += tdb_pack(buf+len, buflen-len, "dddddddddddffffffffff",
652                         info->attributes,
653                         info->priority,
654                         info->default_priority,
655                         info->starttime,
656                         info->untiltime,
657                         info->status,
658                         info->cjobs,
659                         info->averageppm,
660                         info->changeid,
661                         info->c_setprinter,
662                         info->setuptime,
663                         info->servername,
664                         info->printername,
665                         info->sharename,
666                         info->portname,
667                         info->drivername,
668                         info->location,
669                         info->sepfile,
670                         info->printprocessor,
671                         info->datatype,
672                         info->parameters);
673
674         len += pack_devicemode(info->devmode, buf+len, buflen-len);
675         len += pack_specifics(info->specific, buf+len, buflen-len);
676
677         if (buflen != len) {
678                 buf = (char *)Realloc(buf, len);
679                 buflen = len;
680                 goto again;
681         }
682         
683
684         slprintf(key, sizeof(key), "%s%s",
685                  PRINTERS_PREFIX, info->sharename);
686
687         kbuf.dptr = key;
688         kbuf.dsize = strlen(key)+1;
689         dbuf.dptr = buf;
690         dbuf.dsize = len;
691
692         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
693
694         if (ret == -1)
695                 DEBUG(8, ("error updating printer to tdb on disk\n"));
696
697         safe_free(buf);
698
699         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n", 
700                  info->portname, info->drivername, info->portname, len));
701
702         return ret;
703 }
704
705
706 /****************************************************************************
707 ****************************************************************************/
708 BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
709 {
710         NT_PRINTER_PARAM *current;
711         
712         DEBUG(108,("add_a_specific_param\n"));  
713
714         param->next=NULL;
715         
716         if (info_2->specific == NULL)
717         {
718                 info_2->specific=param;
719         }
720         else
721         {
722                 current=info_2->specific;               
723                 while (current->next != NULL) {
724                         current=current->next;
725                 }               
726                 current->next=param;
727         }
728         return (True);
729 }
730
731 /****************************************************************************
732 ****************************************************************************/
733 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
734 {
735         NT_PRINTER_PARAM *current;
736         NT_PRINTER_PARAM *previous;
737         
738         current=info_2->specific;
739         previous=current;
740         
741         if (current==NULL) return (False);
742         
743         if ( !strcmp(current->value, param->value) && 
744             (strlen(current->value)==strlen(param->value)) ) {
745                 DEBUG(109,("deleting first value\n"));
746                 info_2->specific=current->next;
747                 safe_free(current->data);
748                 safe_free(current);
749                 DEBUG(109,("deleted first value\n"));
750                 return (True);
751         }
752
753         current=previous->next;
754                 
755         while ( current!=NULL ) {
756                 if (!strcmp(current->value, param->value) &&
757                     strlen(current->value)==strlen(param->value) ) {
758                         DEBUG(109,("deleting current value\n"));
759                         previous->next=current->next;
760                         safe_free(current->data);
761                         safe_free(current);
762                         DEBUG(109,("deleted current value\n"));
763                         return(True);
764                 }
765                 
766                 previous=previous->next;
767                 current=current->next;
768         }
769         return (False);
770 }
771
772 /****************************************************************************
773  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
774 ****************************************************************************/
775 static void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
776 {
777         NT_PRINTER_PARAM *param = *param_ptr;
778
779         if(param == NULL)
780                 return;
781
782         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
783
784         if(param->data)
785                 safe_free(param->data);
786
787         safe_free(param);
788         *param_ptr = NULL;
789 }
790
791 /****************************************************************************
792  Malloc and return an NT devicemode.
793 ****************************************************************************/
794
795 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
796 {
797 /*
798  * should I init this ones ???
799         nt_devmode->devicename
800 */
801
802         char adevice[32];
803         NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
804
805         if (nt_devmode == NULL) {
806                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
807                 return NULL;
808         }
809
810         ZERO_STRUCTP(nt_devmode);
811
812         snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, default_devicename);
813         fstrcpy(nt_devmode->devicename, adevice);
814         
815         
816         fstrcpy(nt_devmode->formname, "Letter");
817
818         nt_devmode->specversion      = 0x0401;
819         nt_devmode->driverversion    = 0x0400;
820         nt_devmode->size             = 0x00DC;
821         nt_devmode->driverextra      = 0x0000;
822         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY | 
823                                        DEFAULTSOURCE | COPIES | SCALE | 
824                                        PAPERSIZE | ORIENTATION;
825         nt_devmode->orientation      = 1;
826         nt_devmode->papersize        = PAPER_LETTER;
827         nt_devmode->paperlength      = 0;
828         nt_devmode->paperwidth       = 0;
829         nt_devmode->scale            = 0x64;
830         nt_devmode->copies           = 01;
831         nt_devmode->defaultsource    = BIN_FORMSOURCE;
832         nt_devmode->printquality     = 0x0258;
833         nt_devmode->color            = COLOR_MONOCHROME;
834         nt_devmode->duplex           = DUP_SIMPLEX;
835         nt_devmode->yresolution      = 0;
836         nt_devmode->ttoption         = TT_SUBDEV;
837         nt_devmode->collate          = COLLATE_FALSE;
838         nt_devmode->icmmethod        = 0;
839         nt_devmode->icmintent        = 0;
840         nt_devmode->mediatype        = 0;
841         nt_devmode->dithertype       = 0;
842
843         /* non utilisés par un driver d'imprimante */
844         nt_devmode->logpixels        = 0;
845         nt_devmode->bitsperpel       = 0;
846         nt_devmode->pelswidth        = 0;
847         nt_devmode->pelsheight       = 0;
848         nt_devmode->displayflags     = 0;
849         nt_devmode->displayfrequency = 0;
850         nt_devmode->reserved1        = 0;
851         nt_devmode->reserved2        = 0;
852         nt_devmode->panningwidth     = 0;
853         nt_devmode->panningheight    = 0;
854         
855         nt_devmode->private=NULL;
856
857         return nt_devmode;
858 }
859
860 /****************************************************************************
861  Deepcopy an NT devicemode.
862 ****************************************************************************/
863
864 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
865 {
866         NT_DEVICEMODE *new_nt_devicemode = NULL;
867
868         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
869                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
870                 return NULL;
871         }
872
873         new_nt_devicemode->private = NULL;
874         if (nt_devicemode->private != NULL) {
875                 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
876                         safe_free(new_nt_devicemode);
877                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
878                         return NULL;
879         }
880         }
881
882         return new_nt_devicemode;
883 }
884
885 /****************************************************************************
886  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
887 ****************************************************************************/
888
889 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
890 {
891         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
892
893         if(nt_devmode == NULL)
894                 return;
895
896         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
897
898         if(nt_devmode->private)
899                 safe_free(nt_devmode->private);
900
901         safe_free(nt_devmode);
902         *devmode_ptr = NULL;
903 }
904
905 /****************************************************************************
906  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
907 ****************************************************************************/
908 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
909 {
910         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
911         NT_PRINTER_PARAM *param_ptr;
912
913         if(info == NULL)
914                 return;
915
916         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
917
918         free_nt_devicemode(&info->devmode);
919         free_sec_desc_buf(&info->secdesc_buf);
920
921         for(param_ptr = info->specific; param_ptr; ) {
922                 NT_PRINTER_PARAM *tofree = param_ptr;
923
924                 param_ptr = param_ptr->next;
925                 free_nt_printer_param(&tofree);
926         }
927
928         safe_free(*info_ptr);
929         *info_ptr = NULL;
930 }
931
932
933 /****************************************************************************
934 ****************************************************************************/
935 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
936 {
937         int len = 0;
938         NT_DEVICEMODE devmode;
939
940         ZERO_STRUCT(devmode);
941
942         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
943
944         if (!*nt_devmode) return len;
945
946         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
947                           devmode.devicename,
948                           devmode.formname,
949
950                           &devmode.specversion,
951                           &devmode.driverversion,
952                           &devmode.size,
953                           &devmode.driverextra,
954                           &devmode.orientation,
955                           &devmode.papersize,
956                           &devmode.paperlength,
957                           &devmode.paperwidth,
958                           &devmode.scale,
959                           &devmode.copies,
960                           &devmode.defaultsource,
961                           &devmode.printquality,
962                           &devmode.color,
963                           &devmode.duplex,
964                           &devmode.yresolution,
965                           &devmode.ttoption,
966                           &devmode.collate,
967                           &devmode.logpixels,
968                           
969                           &devmode.fields,
970                           &devmode.bitsperpel,
971                           &devmode.pelswidth,
972                           &devmode.pelsheight,
973                           &devmode.displayflags,
974                           &devmode.displayfrequency,
975                           &devmode.icmmethod,
976                           &devmode.icmintent,
977                           &devmode.mediatype,
978                           &devmode.dithertype,
979                           &devmode.reserved1,
980                           &devmode.reserved2,
981                           &devmode.panningwidth,
982                           &devmode.panningheight,
983                           &devmode.private);
984         
985         if (devmode.private)            
986                 len += tdb_unpack(buf+len, buflen-len, "B", &devmode.driverextra, &devmode.private);
987
988         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
989
990         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
991         if (devmode.private)
992                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
993
994         return len;
995 }
996
997 /****************************************************************************
998 ****************************************************************************/
999 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
1000 {
1001         int len = 0;
1002         NT_PRINTER_PARAM param, *p;
1003
1004         *list = NULL;
1005
1006         while (1) {
1007                 len += tdb_unpack(buf+len, buflen-len, "p", &p);
1008                 if (!p) break;
1009
1010                 len += tdb_unpack(buf+len, buflen-len, "fdB",
1011                                   param.value, 
1012                                   &param.type, 
1013                                   &param.data_len,
1014                                   &param.data);
1015                 param.next = *list;
1016                 *list = memdup(&param, sizeof(param));
1017         }
1018
1019         return len;
1020 }
1021
1022
1023 /****************************************************************************
1024 get a default printer info 2 struct
1025 ****************************************************************************/
1026 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1027 {
1028         extern pstring global_myname;
1029         int snum;
1030         NT_PRINTER_INFO_LEVEL_2 info;
1031
1032         ZERO_STRUCT(info);
1033
1034         snum = lp_servicenumber(sharename);
1035
1036         fstrcpy(info.servername, global_myname);
1037         fstrcpy(info.printername, sharename);
1038         fstrcpy(info.portname, sharename);
1039         fstrcpy(info.drivername, lp_printerdriver(snum));
1040         fstrcpy(info.printprocessor, "winprint");
1041         fstrcpy(info.datatype, "RAW");
1042
1043         info.attributes = PRINTER_ATTRIBUTE_SHARED   \
1044                          | PRINTER_ATTRIBUTE_LOCAL  \
1045                          | PRINTER_ATTRIBUTE_RAW_ONLY ;            /* attributes */
1046
1047         info.starttime = 0; /* Minutes since 12:00am GMT */
1048         info.untiltime = 0; /* Minutes since 12:00am GMT */
1049         info.priority = 1;
1050         info.default_priority = 1;
1051
1052         if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
1053                 goto fail;
1054
1055         if (!nt_printing_getsec(sharename, &info.secdesc_buf))
1056                 goto fail;
1057
1058         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
1059         if (! *info_ptr) {
1060                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
1061                 goto fail;
1062         }
1063
1064         return (0);     
1065
1066   fail:
1067
1068         if (info.devmode)
1069                 free_nt_devicemode(&info.devmode);
1070         if (info.secdesc_buf)
1071                 free_sec_desc_buf(&info.secdesc_buf);
1072         return 2;
1073 }
1074
1075 /****************************************************************************
1076 ****************************************************************************/
1077 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1078 {
1079         pstring key;
1080         NT_PRINTER_INFO_LEVEL_2 info;
1081         int len = 0;
1082         TDB_DATA kbuf, dbuf;
1083                 
1084         ZERO_STRUCT(info);
1085
1086         slprintf(key, sizeof(key), "%s%s",
1087                  PRINTERS_PREFIX, sharename);
1088
1089         kbuf.dptr = key;
1090         kbuf.dsize = strlen(key)+1;
1091
1092         dbuf = tdb_fetch(tdb, kbuf);
1093 #if 1 /* JRATEST */
1094         if (!dbuf.dptr) return get_a_printer_2_default(info_ptr, sharename);
1095 #else
1096         if (!dbuf.dptr) return 1;
1097 #endif
1098
1099         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddffffffffff",
1100                         &info.attributes,
1101                         &info.priority,
1102                         &info.default_priority,
1103                         &info.starttime,
1104                         &info.untiltime,
1105                         &info.status,
1106                         &info.cjobs,
1107                         &info.averageppm,
1108                         &info.changeid,
1109                         &info.c_setprinter,
1110                         &info.setuptime,
1111                         info.servername,
1112                         info.printername,
1113                         info.sharename,
1114                         info.portname,
1115                         info.drivername,
1116                         info.location,
1117                         info.sepfile,
1118                         info.printprocessor,
1119                         info.datatype,
1120                         info.parameters);
1121
1122         info.attributes |= PRINTER_ATTRIBUTE_RAW_ONLY; /* Samba has to have raw drivers. */
1123
1124         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
1125         len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
1126
1127 #if 1 /* JRATEST */
1128         nt_printing_getsec(sharename, &info.secdesc_buf);
1129 #endif /* JRATEST */
1130
1131         fstrcpy(info.sharename, "");
1132
1133         safe_free(dbuf.dptr);
1134         *info_ptr=memdup(&info, sizeof(info));
1135
1136         DEBUG(9,("Unpacked printer [%s] running drier [%s]\n",
1137                  sharename, info.drivername));
1138
1139         
1140         return 0;       
1141 }
1142
1143 /****************************************************************************
1144 debugging function, dump at level 6 the struct in the logs
1145 ****************************************************************************/
1146 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1147 {
1148         uint32 success;
1149         NT_PRINTER_INFO_LEVEL_2 *info2;
1150         
1151         DEBUG(106,("Dumping printer at level [%d]\n", level));
1152         
1153         switch (level)
1154         {
1155                 case 2: 
1156                 {
1157                         if (printer.info_2 == NULL)
1158                                 success=5;
1159                         else
1160                         {
1161                                 info2=printer.info_2;
1162                         
1163                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
1164                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
1165                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
1166                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
1167                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
1168                                 DEBUGADD(106,("status:[%d]\n", info2->status));
1169                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
1170                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
1171                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
1172                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
1173                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
1174
1175                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
1176                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
1177                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
1178                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
1179                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
1180                                 DEBUGADD(106,("location:[%s]\n", info2->location));
1181                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
1182                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
1183                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
1184                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
1185                                 success=0;
1186                         }
1187                         break;
1188                 }
1189                 default:
1190                         DEBUGADD(1,("Level not implemented\n"));
1191                         success=1;
1192                         break;
1193         }
1194         
1195         return (success);
1196 }
1197
1198 /*
1199  * The function below are the high level ones.
1200  * only those ones must be called from the spoolss code.
1201  * JFM.
1202  */
1203
1204
1205 /****************************************************************************
1206 ****************************************************************************/
1207 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1208 {
1209         uint32 success;
1210         
1211         dump_a_printer(printer, level); 
1212         
1213         switch (level)
1214         {
1215                 case 2: 
1216                 {
1217                         success=add_a_printer_2(printer.info_2);
1218                         break;
1219                 }
1220                 default:
1221                         success=1;
1222                         break;
1223         }
1224         
1225         return (success);
1226 }
1227
1228 /****************************************************************************
1229  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
1230 ****************************************************************************/
1231
1232 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
1233 {
1234         uint32 success;
1235         NT_PRINTER_INFO_LEVEL *printer = NULL;
1236         
1237         *pp_printer = NULL;
1238
1239         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
1240
1241         switch (level)
1242         {
1243                 case 2: 
1244                 {
1245                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
1246                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
1247                                 return 1;
1248                         }
1249                         ZERO_STRUCTP(printer);
1250                         success=get_a_printer_2(&printer->info_2, sharename);
1251                         if (success == 0) {
1252                                 dump_a_printer(*printer, level);
1253                                 *pp_printer = printer;
1254                         } else {
1255                                 safe_free(printer);
1256                         }
1257                         break;
1258                 }
1259                 default:
1260                         success=1;
1261                         break;
1262         }
1263         
1264         DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
1265
1266         return (success);
1267 }
1268
1269 /****************************************************************************
1270  Deletes a NT_PRINTER_INFO_LEVEL struct.
1271 ****************************************************************************/
1272
1273 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
1274 {
1275         uint32 success;
1276         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
1277
1278         DEBUG(104,("freeing a printer at level [%d]\n", level));
1279
1280         if (printer == NULL)
1281                 return 0;
1282         
1283         switch (level)
1284         {
1285                 case 2: 
1286                 {
1287                         if (printer->info_2 != NULL)
1288                         {
1289                                 free_nt_printer_info_level_2(&printer->info_2);
1290                                 success=0;
1291                         }
1292                         else
1293                         {
1294                                 success=4;
1295                         }
1296                         break;
1297                 }
1298                 default:
1299                         success=1;
1300                         break;
1301         }
1302
1303         safe_free(printer);
1304         *pp_printer = NULL;
1305         return (success);
1306 }
1307
1308 /****************************************************************************
1309 ****************************************************************************/
1310 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1311 {
1312         uint32 success;
1313         DEBUG(104,("adding a printer at level [%d]\n", level));
1314         dump_a_printer_driver(driver, level);
1315         
1316         switch (level)
1317         {
1318                 case 3: 
1319                 {
1320                         success=add_a_printer_driver_3(driver.info_3);
1321                         break;
1322                 }
1323
1324                 case 6: 
1325                 {
1326                         success=add_a_printer_driver_6(driver.info_6);
1327                         break;
1328                 }
1329                 default:
1330                         success=1;
1331                         break;
1332         }
1333         
1334         return (success);
1335 }
1336 /****************************************************************************
1337 ****************************************************************************/
1338 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, 
1339                             fstring printername, fstring architecture)
1340 {
1341         uint32 success;
1342         
1343         switch (level)
1344         {
1345                 case 3: 
1346                 {
1347                         success=get_a_printer_driver_3(&(driver->info_3), 
1348                                                        printername,
1349                                                        architecture);
1350                         break;
1351                 }
1352                 default:
1353                         success=1;
1354                         break;
1355         }
1356         
1357         if (success == 0) dump_a_printer_driver(*driver, level);
1358         return (success);
1359 }
1360
1361 /****************************************************************************
1362 ****************************************************************************/
1363 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1364 {
1365         uint32 success;
1366         
1367         switch (level)
1368         {
1369                 case 3: 
1370                 {
1371                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1372                         if (driver.info_3 != NULL)
1373                         {
1374                                 info3=driver.info_3;
1375                                 safe_free(info3->dependentfiles);
1376                                 ZERO_STRUCTP(info3);
1377                                 safe_free(info3);
1378                                 success=0;
1379                         }
1380                         else
1381                         {
1382                                 success=4;
1383                         }
1384                         break;
1385                 }
1386                 case 6: 
1387                 {
1388                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
1389                         if (driver.info_6 != NULL)
1390                         {
1391                                 info6=driver.info_6;
1392                                 safe_free(info6->dependentfiles);
1393                                 safe_free(info6->previousnames);
1394                                 ZERO_STRUCTP(info6);
1395                                 safe_free(info6);
1396                                 success=0;
1397                         }
1398                         else
1399                         {
1400                                 success=4;
1401                         }
1402                         break;
1403                 }
1404                 default:
1405                         success=1;
1406                         break;
1407         }
1408         return (success);
1409 }
1410
1411 /****************************************************************************
1412 ****************************************************************************/
1413 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
1414                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
1415 {
1416         /* right now that's enough ! */ 
1417         NT_PRINTER_PARAM *param;
1418         int i=0;
1419         
1420         param=printer.info_2->specific;
1421         
1422         while (param != NULL && i < param_index) {
1423                 param=param->next;
1424                 i++;
1425         }
1426         
1427         if (param == NULL)
1428                 return False;
1429
1430         /* exited because it exist */
1431         *type=param->type;              
1432         StrnCpy(value, param->value, sizeof(fstring)-1);
1433         *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1434         if(*data == NULL)
1435                 return False;
1436         ZERO_STRUCTP(*data);
1437         memcpy(*data, param->data, param->data_len);
1438         *len=param->data_len;
1439         return True;
1440 }
1441
1442 /****************************************************************************
1443 ****************************************************************************/
1444 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, 
1445                         fstring value, uint8 **data, uint32 *type, uint32 *len)
1446 {
1447         /* right now that's enough ! */ 
1448         NT_PRINTER_PARAM *param;
1449         
1450         DEBUG(105, ("get_specific_param\n"));
1451         
1452         param=printer.info_2->specific;
1453                 
1454         while (param != NULL)
1455         {
1456                 if ( !strcmp(value, param->value) 
1457                     && strlen(value)==strlen(param->value))
1458                         break;
1459                         
1460                 param=param->next;
1461         }
1462         
1463         DEBUG(106, ("found one param\n"));
1464         if (param != NULL)
1465         {
1466                 /* exited because it exist */
1467                 *type=param->type;      
1468                 
1469                 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1470                 if(*data == NULL)
1471                         return False;
1472                 memcpy(*data, param->data, param->data_len);
1473                 *len=param->data_len;
1474
1475                 DEBUG(106, ("exit of get_specific_param:true\n"));
1476                 return (True);
1477         }
1478         DEBUG(106, ("exit of get_specific_param:false\n"));
1479         return (False);
1480 }
1481
1482
1483 /****************************************************************************
1484 store a security desc for a printer
1485 ****************************************************************************/
1486 uint32 nt_printing_setsec(char *printername, struct current_user *user,
1487                           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 acc_granted, status;
1494
1495         /* Get old security descriptor */
1496
1497         if (!nt_printing_getsec(printername, &old_secdesc_ctr)) {
1498                 DEBUG(3, ("could not get old security descriptor for "
1499                           "printer %s", printername));
1500                 return ERROR_INVALID_FUNCTION;
1501         }
1502
1503         /* Check the user has permissions to change the security
1504            descriptor.  By experimentation with two NT machines, the user
1505            requires Full Access to the printer to change security
1506            information. */ 
1507
1508         if (!se_access_check(old_secdesc_ctr->sec, user->uid, user->gid,
1509                              user->ngroups, user->groups, 
1510                              PRINTER_ACE_FULL_CONTROL, &acc_granted,
1511                              &status)) {
1512                 DEBUG(3, ("security descriptor change denied by existing "
1513                           "security descriptor\n"));
1514                 free_sec_desc_buf(&old_secdesc_ctr);
1515                 return status;
1516         }
1517
1518         /* The old owner and group sids of the security descriptor are not
1519            present when new ACEs are added or removed by changing printer
1520            permissions through NT.  If they are NULL in the new security
1521            descriptor then copy them over from the old one. */
1522
1523         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
1524                 DOM_SID *owner_sid, *group_sid;
1525                 SEC_DESC *psd = NULL;
1526                 size_t size;
1527
1528                 /* Pick out correct owner and group sids */
1529
1530                 owner_sid = secdesc_ctr->sec->owner_sid ?
1531                         secdesc_ctr->sec->owner_sid :
1532                         old_secdesc_ctr->sec->owner_sid;
1533
1534                 group_sid = secdesc_ctr->sec->grp_sid ?
1535                         secdesc_ctr->sec->grp_sid :
1536                         old_secdesc_ctr->sec->grp_sid;
1537
1538                 /* Make a deep copy of the security descriptor */
1539
1540                 psd = make_sec_desc(secdesc_ctr->sec->revision,
1541                                     secdesc_ctr->sec->type,
1542                                     owner_sid, group_sid,
1543                                     secdesc_ctr->sec->sacl,
1544                                     secdesc_ctr->sec->dacl,
1545                                     &size);
1546
1547                 new_secdesc_ctr = make_sec_desc_buf(size, psd);
1548
1549                 /* Free up memory */
1550
1551                 free_sec_desc(&psd);
1552         }
1553
1554         if (!new_secdesc_ctr) {
1555                 new_secdesc_ctr = secdesc_ctr;
1556         }
1557
1558         /* Store the security descriptor in a tdb */
1559
1560         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) + 
1561                  sizeof(SEC_DESC_BUF), 4, MARSHALL);
1562
1563         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr, 
1564                              &ps, 1)) {
1565                 status = ERROR_INVALID_FUNCTION;
1566                 goto out;
1567         }
1568
1569         slprintf(key, sizeof(key), "SECDESC/%s", printername);
1570
1571         if (tdb_prs_store(tdb, key, &ps)==0) {
1572                 status = 0;
1573         } else {
1574                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
1575                 status = ERROR_INVALID_FUNCTION;
1576         }
1577
1578         /* Free mallocated memory */
1579
1580  out:
1581         free_sec_desc_buf(&old_secdesc_ctr);
1582
1583         if (new_secdesc_ctr != secdesc_ctr) {
1584                 free_sec_desc_buf(&new_secdesc_ctr);
1585         }
1586
1587         prs_mem_free(&ps);
1588         return status;
1589 }
1590
1591 /****************************************************************************
1592  Construct a default security descriptor buffer for a printer.
1593 ****************************************************************************/
1594
1595 static SEC_DESC_BUF *construct_default_printer_sdb(void)
1596 {
1597         extern DOM_SID global_sid_World; 
1598         SEC_ACE ace;
1599         SEC_ACCESS sa;
1600         SEC_ACL *psa = NULL;
1601         SEC_DESC_BUF *sdb = NULL;
1602         SEC_DESC *psd = NULL;
1603         DOM_SID owner_sid;
1604         size_t sd_size;
1605         uint8 name_type;
1606
1607         /* Create an ACE where Everyone is allowed to print */
1608
1609         init_sec_access(&sa, PRINTER_ACE_PRINT);
1610         init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1611                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1612
1613         /* Make the security descriptor owned by the Administrators group
1614            on the PDC of the domain. */
1615
1616         if (!winbind_lookup_name("Administrator", &owner_sid, &name_type)) {
1617                 /*
1618                  * Backup - make owner the everyone sid. This may be a security
1619                  * hole for print control .... check. JRA.
1620                  */
1621                 sid_copy( &owner_sid, &global_sid_World);
1622         }
1623
1624         /* The ACL revision number in rpc_secdesc.h differs from the one
1625            created by NT when setting ACE entries in printer
1626            descriptors.  NT4 complains about the property being edited by a
1627            NT5 machine. */
1628
1629 #define NT4_ACL_REVISION 0x2
1630
1631         if ((psa = make_sec_acl(NT4_ACL_REVISION, 1, &ace)) != NULL) {
1632                 psd = make_sec_desc(SEC_DESC_REVISION, 
1633                                     SEC_DESC_SELF_RELATIVE | 
1634                                     SEC_DESC_DACL_PRESENT,
1635                                     &owner_sid, NULL,
1636                                     NULL, psa, &sd_size);
1637                 free_sec_acl(&psa);
1638         }
1639
1640         if (!psd) {
1641                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1642                 return NULL;
1643         }
1644
1645         sdb = make_sec_desc_buf(sd_size, psd);
1646
1647         DEBUG(4,("construct_default_printer_sdb: size = %u.\n", 
1648                  (unsigned int)sd_size));
1649
1650         free_sec_desc(&psd);
1651         return sdb;
1652 }
1653
1654 /****************************************************************************
1655  Get a security desc for a printer.
1656 ****************************************************************************/
1657
1658 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
1659 {
1660         prs_struct ps;
1661         fstring key;
1662
1663         slprintf(key, sizeof(key), "SECDESC/%s", printername);
1664
1665         if (tdb_prs_fetch(tdb, key, &ps)!=0 ||
1666             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
1667
1668                 DEBUG(4,("using default secdesc for %s\n", printername));
1669
1670                 if (!(*secdesc_ctr = construct_default_printer_sdb()))
1671                         return False;
1672
1673                 return True;
1674         }
1675
1676         prs_mem_free(&ps);
1677         return True;
1678 }
1679
1680 /* error code:
1681         0: everything OK
1682         1: level not implemented
1683         2: file doesn't exist
1684         3: can't allocate memory
1685         4: can't free memory
1686         5: non existant struct
1687 */
1688
1689 /*
1690         A printer and a printer driver are 2 different things.
1691         NT manages them separatelly, Samba does the same.
1692         Why ? Simply because it's easier and it makes sense !
1693         
1694         Now explanation: You have 3 printers behind your samba server,
1695         2 of them are the same make and model (laser A and B). But laser B 
1696         has an 3000 sheet feeder and laser A doesn't such an option.
1697         Your third printer is an old dot-matrix model for the accounting :-).
1698         
1699         If the /usr/local/samba/lib directory (default dir), you will have
1700         5 files to describe all of this.
1701         
1702         3 files for the printers (1 by printer):
1703                 NTprinter_laser A
1704                 NTprinter_laser B
1705                 NTprinter_accounting
1706         2 files for the drivers (1 for the laser and 1 for the dot matrix)
1707                 NTdriver_printer model X
1708                 NTdriver_printer model Y
1709
1710 jfm: I should use this comment for the text file to explain 
1711         same thing for the forms BTW.
1712         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1713
1714 */
1715
1716 /* Check a user has permissions to perform the given operation */
1717
1718 BOOL print_access_check(struct current_user *user, int snum,
1719                         uint32 required_access)
1720 {
1721         SEC_DESC_BUF *secdesc = NULL;
1722         uint32 access_granted, status;
1723         BOOL result;
1724         char *pname;
1725         int i;
1726         
1727         /* Get printer name */
1728
1729         pname = PRINTERNAME(snum);
1730         if (!pname || !*pname) pname = SERVICE(snum);
1731
1732         /* Get printer security descriptor */
1733
1734         nt_printing_getsec(pname, &secdesc);
1735
1736         /* The ACE for Full Control in a printer security descriptor
1737            doesn't seem to map properly to the access checking model.  For
1738            it to work properly it should be the logical OR of all the other
1739            values, i.e PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT.
1740            This would cause the access check to simply fall out when we
1741            check against any subset of these bits.  To get things to work,
1742            change every ACE mask of PRINTER_ACE_FULL_CONTROL to 
1743            PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before
1744            performing the access check.  I'm sure there is a better way to
1745            do this! */
1746
1747         if (secdesc && secdesc->sec && secdesc->sec->dacl &&
1748             secdesc->sec->dacl->ace) {
1749                 for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
1750                         if (secdesc->sec->dacl->ace[i].info.mask ==
1751                             PRINTER_ACE_FULL_CONTROL) {
1752                                 secdesc->sec->dacl->ace[i].info.mask =
1753                                         PRINTER_ACE_MANAGE_DOCUMENTS | 
1754                                         PRINTER_ACE_PRINT;
1755                         }
1756                 }
1757         }
1758
1759         /* Check access */
1760
1761         result = se_access_check(secdesc->sec, user->uid, user->gid,
1762                                  user->ngroups, user->groups,
1763                                  required_access, &access_granted, &status);
1764
1765         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
1766
1767         /* Free mallocated memory */
1768
1769         free_sec_desc_buf(&secdesc);
1770
1771         return result;
1772 }