9661c9265fe3aac1916b5a7cfb4cc40c81b8070f
[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", 0x2, 0x34b5b, 0x44367, 0x0, 0x0, 0x34b5b, 0x44367},
41         {"A4", 0x2, 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, uint32 version)
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/%d/", DRIVERS_PREFIX, short_archi, version);
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 BOOL 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 ) && 
271                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
272
273         if (archi_table[i].long_archi==NULL) {
274                 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
275                 return FALSE;
276         }
277
278         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
279
280         DEBUGADD(108,("index: [%d]\n", i));
281         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
282         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
283         
284         return TRUE;
285 }
286
287 /****************************************************************************
288 ****************************************************************************/
289 static void clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
290 {
291         fstring architecture;
292         fstring new_name;
293         char *p;
294         int i;
295         
296         /* jfm:7/16/2000 the client always sends the cversion=0.
297          * The server should check which version the driver is by reading the PE header
298          * of driver->driverpath.
299          *
300          * For Windows 95/98 the version is 0 (so the value sent is correct)
301          * For Windows NT (the architecture doesn't matter)
302          *      NT 3.1: cversion=0
303          *      NT 3.5/3.51: cversion=1
304          *      NT 4: cversion=2
305          *      NT2K: cversion=3
306          */
307
308         get_short_archi(architecture, driver->environment);
309
310         /* if it's Windows 95/98, we keep the version at 0
311          * jfmxxx: I need to redo that more correctly for NT2K.
312          */
313          
314         if (StrCaseCmp(driver->environment, "Windows 4.0")==0)
315                 driver->cversion=0;
316         else
317                 driver->cversion=2;
318
319         /* clean up the driver name.
320          * we can get .\driver.dll
321          * or worse c:\windows\system\driver.dll !
322          */
323         /* using an intermediate string to not have overlaping memcpy()'s */
324         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
325                 fstrcpy(new_name, p+1);
326                 fstrcpy(driver->driverpath, new_name);
327         }
328
329         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
330                 fstrcpy(new_name, p+1);
331                 fstrcpy(driver->datafile, new_name);
332         }
333
334         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
335                 fstrcpy(new_name, p+1);
336                 fstrcpy(driver->configfile, new_name);
337         }
338
339         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
340                 fstrcpy(new_name, p+1);
341                 fstrcpy(driver->helpfile, new_name);
342         }
343
344         if (driver->dependentfiles) {
345                 for (i=0; *driver->dependentfiles[i]; i++) {
346                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
347                                 fstrcpy(new_name, p+1);
348                                 fstrcpy(driver->dependentfiles[i], new_name);
349                         }
350                 }
351         }
352 }
353
354 /****************************************************************************
355 ****************************************************************************/
356 static void clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
357 {
358
359 }
360
361 /****************************************************************************
362 ****************************************************************************/
363 void clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level)
364 {
365         switch (level) {
366                 case 3:
367                 {
368                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
369                         driver=driver_abstract.info_3;
370                         clean_up_driver_struct_level_3(driver);
371                         break;
372                 }
373                 case 6:
374                 {
375                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
376                         driver=driver_abstract.info_6;
377                         clean_up_driver_struct_level_6(driver);
378                         break;
379                 }
380         }
381 }
382
383 /****************************************************************************
384 ****************************************************************************/
385 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user)
386 {
387         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
388         fstring architecture;
389         fstring clean_driver_name;
390         pstring new_dir;
391         pstring old_name;
392         pstring new_name;
393         fstring user_name;
394         connection_struct *conn;
395         pstring inbuf;
396         pstring outbuf;
397         struct smb_passwd *smb_pass;
398         int ecode;
399         int outsize = 0;
400         int i;
401
402         if (level==3)
403                 driver=driver_abstract.info_3;
404         
405         get_short_archi(architecture, driver->environment);
406
407         /* clean up the driver's name */
408         fstrcpy(clean_driver_name, driver->name);
409         all_string_sub(clean_driver_name, "/", "#", 0);
410         
411         /* connect to the print$ share under the same account as the user connected to the rpc pipe */  
412         fstrcpy(user_name, uidtoname(user->uid));
413         if((smb_pass = getsmbpwnam(user_name)) == NULL) {
414                 DEBUG(0,("move_driver_to_download_area: Unable to get smbpasswd entry for user %s\n",
415                                 user_name ));
416                 return False;
417         }
418
419         conn = make_connection("print$", uidtoname(user->uid), smb_pass->smb_nt_passwd, 24, "A:", user->vuid, &ecode);
420
421         if (conn == NULL) {
422                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
423                 return False;
424         }
425
426         /* 
427          * make the directories version and version\driver_name 
428          * under the architecture directory.
429          */
430         DEBUG(5,("Creating first directory\n"));
431         slprintf(new_dir, sizeof(new_dir), "%s\\%d", architecture, driver->cversion);
432         mkdir_internal(conn, inbuf, outbuf, new_dir);
433
434         slprintf(new_dir, sizeof(new_dir), "%s\\%d\\%s", architecture, driver->cversion, clean_driver_name);
435         mkdir_internal(conn, inbuf, outbuf, new_dir);
436
437         /* move all the files, one by one, 
438          * from archi\filexxx.yyy to
439          * archi\version\driver name\filexxx.yyy 
440          */
441
442         DEBUG(5,("Moving file now !\n"));
443         slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->driverpath);       
444         slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->driverpath);    
445         if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
446                 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
447                                 old_name, new_name ));
448                 return False;
449         }
450
451         slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->datafile); 
452         slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->datafile);      
453         if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
454                 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
455                                 old_name, new_name ));
456                 return False;
457         }
458
459         slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->configfile);       
460         slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->configfile);    
461         if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
462                 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
463                         old_name, new_name ));
464                 return False;
465         }
466
467         slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->helpfile); 
468         slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->helpfile);      
469         if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
470                 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
471                         old_name, new_name ));
472                 return False;
473         }
474
475         if (driver->dependentfiles) {
476                 for (i=0; *driver->dependentfiles[i]; i++) {
477                         slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->dependentfiles[i]);        
478                         slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->dependentfiles[i]);     
479                         if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
480                                 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
481                                         old_name, new_name ));
482                                 return False;
483                         }
484                 }
485         }
486
487         close_cnum(conn, user->vuid);
488
489         return True;
490 }
491
492 /****************************************************************************
493 ****************************************************************************/
494 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
495 {
496         int len, buflen;
497         fstring architecture;
498         pstring directory;
499         fstring clean_driver_name;
500         pstring temp_name;
501         pstring key;
502         char *buf;
503         int i, ret;
504         TDB_DATA kbuf, dbuf;
505
506         get_short_archi(architecture, driver->environment);
507
508         /* The names are relative. We store them in the form: \print$\arch\version\printer-name\driver.xxx
509          * \\server is added in the rpc server layer.
510          * It does make sense to NOT store the server's name in the printer TDB.
511          */
512
513         /* clean up the driver's name */
514         fstrcpy(clean_driver_name, driver->name);
515         all_string_sub(clean_driver_name, "/", "#", 0);
516         
517         slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\%s\\", architecture, driver->cversion, clean_driver_name);
518
519         
520         fstrcpy(temp_name, driver->driverpath);
521         slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
522
523         fstrcpy(temp_name, driver->datafile);
524         slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
525
526         fstrcpy(temp_name, driver->configfile);
527         slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
528
529         fstrcpy(temp_name, driver->helpfile);
530         slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
531
532         if (driver->dependentfiles) {
533                 for (i=0; *driver->dependentfiles[i]; i++) {
534                         fstrcpy(temp_name, driver->dependentfiles[i]);
535                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
536                 }
537         }
538
539         slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
540
541         buf = NULL;
542         len = buflen = 0;
543
544  again:
545         len = 0;
546         len += tdb_pack(buf+len, buflen-len, "dffffffff", 
547                         driver->cversion,
548                         driver->name,
549                         driver->environment,
550                         driver->driverpath,
551                         driver->datafile,
552                         driver->configfile,
553                         driver->helpfile,
554                         driver->monitorname,
555                         driver->defaultdatatype);
556
557         if (driver->dependentfiles) {
558                 for (i=0; *driver->dependentfiles[i]; i++) {
559                         len += tdb_pack(buf+len, buflen-len, "f", 
560                                         driver->dependentfiles[i]);
561                 }
562         }
563
564         if (len != buflen) {
565                 buf = (char *)Realloc(buf, len);
566                 buflen = len;
567                 goto again;
568         }
569
570
571         kbuf.dptr = key;
572         kbuf.dsize = strlen(key)+1;
573         dbuf.dptr = buf;
574         dbuf.dsize = len;
575         
576         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
577
578         safe_free(buf);
579         return ret;
580 }
581
582 /****************************************************************************
583 ****************************************************************************/
584 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
585 {
586         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
587
588         ZERO_STRUCT(info3);
589         info3.cversion = driver->version;
590         fstrcpy(info3.environment,driver->environment);
591         fstrcpy(info3.driverpath,driver->driverpath);
592         fstrcpy(info3.datafile,driver->datafile);
593         fstrcpy(info3.configfile,driver->configfile);
594         fstrcpy(info3.helpfile,driver->helpfile);
595         fstrcpy(info3.monitorname,driver->monitorname);
596         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
597         info3.dependentfiles = driver->dependentfiles;
598
599         return add_a_printer_driver_3(&info3);
600 }
601
602
603 /****************************************************************************
604 ****************************************************************************/
605 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
606 {
607         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
608
609         ZERO_STRUCT(info);
610
611         fstrcpy(info.name, in_prt);
612         fstrcpy(info.defaultdatatype, "RAW");
613         
614         fstrcpy(info.driverpath, "");
615         fstrcpy(info.datafile, "");
616         fstrcpy(info.configfile, "");
617         fstrcpy(info.helpfile, "");
618
619         if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
620                 return ERROR_NOT_ENOUGH_MEMORY;
621
622         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
623         fstrcpy(info.dependentfiles[0], "");
624
625         *info_ptr = memdup(&info, sizeof(info));
626         
627         return 0;       
628 }
629
630 /****************************************************************************
631 ****************************************************************************/
632 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
633 {
634         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
635         TDB_DATA kbuf, dbuf;
636         fstring architecture;
637         int len = 0;
638         int i;
639         pstring key;
640
641         ZERO_STRUCT(driver);
642
643         get_short_archi(architecture, in_arch);
644
645         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
646
647         slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
648
649         kbuf.dptr = key;
650         kbuf.dsize = strlen(key)+1;
651         
652         dbuf = tdb_fetch(tdb, kbuf);
653 #if 0
654         if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
655 #else
656         if (!dbuf.dptr) return 5;
657 #endif
658         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff", 
659                           &driver.cversion,
660                           driver.name,
661                           driver.environment,
662                           driver.driverpath,
663                           driver.datafile,
664                           driver.configfile,
665                           driver.helpfile,
666                           driver.monitorname,
667                           driver.defaultdatatype);
668
669         i=0;
670         while (len < dbuf.dsize) {
671                 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
672                                                          sizeof(fstring)*(i+2));
673                 if (driver.dependentfiles == NULL)
674                         break;
675
676                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", 
677                                   &driver.dependentfiles[i]);
678                 i++;
679         }
680         if (driver.dependentfiles != NULL)
681                 fstrcpy(driver.dependentfiles[i], "");
682
683         safe_free(dbuf.dptr);
684
685         if (len != dbuf.dsize) {
686                 if (driver.dependentfiles != NULL)
687                         safe_free(driver.dependentfiles);
688
689                 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
690         }
691
692         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
693
694         return 0;
695 }
696
697 /****************************************************************************
698 ****************************************************************************/
699 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
700 {
701         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
702         TDB_DATA kbuf, dbuf;
703         pstring key;
704         int i;
705         line[0] = '\0';
706
707         slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
708         DEBUG(10,("driver key: [%s]\n", key));
709         
710         kbuf.dptr = key;
711         kbuf.dsize = strlen(key)+1;
712         if (!tdb_exists(tdb, kbuf)) return False;
713
714         ZERO_STRUCT(info3);
715         get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
716         
717     DEBUGADD(10,("info3->name            [%s]\n", info3->name));
718     DEBUGADD(10,("info3->datafile        [%s]\n", info3->datafile));
719     DEBUGADD(10,("info3->helpfile        [%s]\n", info3->helpfile));
720     DEBUGADD(10,("info3->monitorname     [%s]\n", info3->monitorname));
721     DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
722         for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
723     DEBUGADD(10,("info3->dependentfiles  [%s]\n", info3->dependentfiles[i]));
724     }
725     DEBUGADD(10,("info3->environment     [%s]\n", info3->environment));
726     DEBUGADD(10,("info3->driverpath      [%s]\n", info3->driverpath));
727     DEBUGADD(10,("info3->configfile      [%s]\n", info3->configfile));
728
729         /*pstrcat(line, info3->name);             pstrcat(line, ":");*/
730         pstrcat(line, info3->configfile);
731     pstrcat(line, ":");
732         pstrcat(line, info3->datafile);
733     pstrcat(line, ":");
734         pstrcat(line, info3->helpfile);
735     pstrcat(line, ":");
736         pstrcat(line, info3->monitorname);
737     pstrcat(line, ":");
738         pstrcat(line, "RAW");                /*info3->defaultdatatype);*/
739     pstrcat(line, ":");
740
741         for (i=0; info3->dependentfiles &&
742                  *info3->dependentfiles[i]; i++) {
743                 if (i) pstrcat(line, ",");               /* don't end in a "," */
744                 pstrcat(line, info3->dependentfiles[i]);
745         }
746         
747         free(info3);
748
749         return True;    
750 }
751
752 /****************************************************************************
753 debugging function, dump at level 6 the struct in the logs
754 ****************************************************************************/
755 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
756 {
757         uint32 success;
758         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
759         int i;
760         
761         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
762         
763         switch (level)
764         {
765                 case 3: 
766                 {
767                         if (driver.info_3 == NULL)
768                                 success=5;
769                         else {
770                                 info3=driver.info_3;
771                         
772                                 DEBUGADD(106,("version:[%d]\n",         info3->cversion));
773                                 DEBUGADD(106,("name:[%s]\n",            info3->name));
774                                 DEBUGADD(106,("environment:[%s]\n",     info3->environment));
775                                 DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
776                                 DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
777                                 DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
778                                 DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
779                                 DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
780                                 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
781                                 
782                                 for (i=0; info3->dependentfiles &&
783                                           *info3->dependentfiles[i]; i++) {
784                                         DEBUGADD(106,("dependentfile:[%s]\n", 
785                                                       info3->dependentfiles[i]));
786                                 }
787                                 success=0;
788                         }
789                         break;
790                 }
791                 default:
792                         DEBUGADD(1,("Level not implemented\n"));
793                         success=1;
794                         break;
795         }
796         
797         return (success);
798 }
799
800 /****************************************************************************
801 ****************************************************************************/
802 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
803 {
804         int len = 0;
805
806         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
807
808         if (!nt_devmode) return len;
809
810         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
811                         nt_devmode->devicename,
812                         nt_devmode->formname,
813
814                         nt_devmode->specversion,
815                         nt_devmode->driverversion,
816                         nt_devmode->size,
817                         nt_devmode->driverextra,
818                         nt_devmode->orientation,
819                         nt_devmode->papersize,
820                         nt_devmode->paperlength,
821                         nt_devmode->paperwidth,
822                         nt_devmode->scale,
823                         nt_devmode->copies,
824                         nt_devmode->defaultsource,
825                         nt_devmode->printquality,
826                         nt_devmode->color,
827                         nt_devmode->duplex,
828                         nt_devmode->yresolution,
829                         nt_devmode->ttoption,
830                         nt_devmode->collate,
831                         nt_devmode->logpixels,
832                         
833                         nt_devmode->fields,
834                         nt_devmode->bitsperpel,
835                         nt_devmode->pelswidth,
836                         nt_devmode->pelsheight,
837                         nt_devmode->displayflags,
838                         nt_devmode->displayfrequency,
839                         nt_devmode->icmmethod,
840                         nt_devmode->icmintent,
841                         nt_devmode->mediatype,
842                         nt_devmode->dithertype,
843                         nt_devmode->reserved1,
844                         nt_devmode->reserved2,
845                         nt_devmode->panningwidth,
846                         nt_devmode->panningheight,
847                         nt_devmode->private);
848
849         
850         if (nt_devmode->private) {
851                 len += tdb_pack(buf+len, buflen-len, "B",
852                                 nt_devmode->driverextra,
853                                 nt_devmode->private);
854         }
855
856         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
857
858         return len;
859 }
860
861 /****************************************************************************
862 ****************************************************************************/
863 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
864 {
865         int len = 0;
866
867         while (param != NULL) {
868                 len += tdb_pack(buf+len, buflen-len, "pfdB",
869                                 param,
870                                 param->value, 
871                                 param->type, 
872                                 param->data_len,
873                                 param->data);
874                 param=param->next;      
875         }
876
877         len += tdb_pack(buf+len, buflen-len, "p", param);
878
879         return len;
880 }
881
882
883 /****************************************************************************
884 delete a printer - this just deletes the printer info file, any open
885 handles are not affected
886 ****************************************************************************/
887 uint32 del_a_printer(char *sharename)
888 {
889         pstring key;
890         TDB_DATA kbuf;
891
892         slprintf(key, sizeof(key), "%s%s",
893                  PRINTERS_PREFIX, sharename);
894
895         kbuf.dptr=key;
896         kbuf.dsize=strlen(key)+1;
897
898         tdb_delete(tdb, kbuf);
899         return 0;
900 }
901
902 /****************************************************************************
903 ****************************************************************************/
904 static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
905 {
906         pstring key;
907         char *buf;
908         int buflen, len, ret;
909         TDB_DATA kbuf, dbuf;
910         NTTIME time_nt;
911         time_t time_unix = time(NULL);
912         
913         /* 
914          * in addprinter: no servername and the printer is the name
915          * in setprinter: servername is \\server
916          *                and printer is \\server\\printer
917          *
918          * Samba manages only local printers.
919          * we currently don't support things like path=\\other_server\printer
920          */
921
922         if (info->servername[0]!='\0') {
923                 trim_string(info->printername, info->servername, NULL);
924                 trim_string(info->printername, "\\", NULL);
925                 info->servername[0]='\0';
926         }
927
928         /*
929          * JFM: one day I'll forget.
930          * below that's info->portname because that's the SAMBA sharename
931          * and I made NT 'thinks' it's the portname
932          * the info->sharename is the thing you can name when you add a printer
933          * that's the short-name when you create shared printer for 95/98
934          * So I've made a limitation in SAMBA: you can only have 1 printer model
935          * behind a SAMBA share.
936          */
937
938         unix_to_nt_time(&time_nt, time_unix);
939         info->changeid=time_nt.low;
940         info->c_setprinter++;
941
942         buf = NULL;
943         buflen = 0;
944
945  again: 
946         len = 0;
947         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffffffff",
948                         info->attributes,
949                         info->priority,
950                         info->default_priority,
951                         info->starttime,
952                         info->untiltime,
953                         info->status,
954                         info->cjobs,
955                         info->averageppm,
956                         info->changeid,
957                         info->c_setprinter,
958                         info->setuptime,
959                         info->servername,
960                         info->printername,
961                         info->sharename,
962                         info->portname,
963                         info->drivername,
964                         info->comment,
965                         info->location,
966                         info->sepfile,
967                         info->printprocessor,
968                         info->datatype,
969                         info->parameters);
970
971         len += pack_devicemode(info->devmode, buf+len, buflen-len);
972         len += pack_specifics(info->specific, buf+len, buflen-len);
973
974         if (buflen != len) {
975                 buf = (char *)Realloc(buf, len);
976                 buflen = len;
977                 goto again;
978         }
979         
980
981         slprintf(key, sizeof(key), "%s%s",
982                  PRINTERS_PREFIX, info->sharename);
983
984         kbuf.dptr = key;
985         kbuf.dsize = strlen(key)+1;
986         dbuf.dptr = buf;
987         dbuf.dsize = len;
988
989         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
990
991         if (ret == -1)
992                 DEBUG(8, ("error updating printer to tdb on disk\n"));
993
994         safe_free(buf);
995
996         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n", 
997                  info->sharename, info->drivername, info->portname, len));
998
999         return ret;
1000 }
1001
1002
1003 /****************************************************************************
1004 ****************************************************************************/
1005 BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1006 {
1007         NT_PRINTER_PARAM *current;
1008         
1009         DEBUG(108,("add_a_specific_param\n"));  
1010
1011         param->next=NULL;
1012         
1013         if (info_2->specific == NULL)
1014         {
1015                 info_2->specific=param;
1016         }
1017         else
1018         {
1019                 current=info_2->specific;               
1020                 while (current->next != NULL) {
1021                         current=current->next;
1022                 }               
1023                 current->next=param;
1024         }
1025         return (True);
1026 }
1027
1028 /****************************************************************************
1029 ****************************************************************************/
1030 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1031 {
1032         NT_PRINTER_PARAM *current;
1033         NT_PRINTER_PARAM *previous;
1034         
1035         current=info_2->specific;
1036         previous=current;
1037         
1038         if (current==NULL) return (False);
1039         
1040         if ( !strcmp(current->value, param->value) && 
1041             (strlen(current->value)==strlen(param->value)) ) {
1042                 DEBUG(109,("deleting first value\n"));
1043                 info_2->specific=current->next;
1044                 safe_free(current->data);
1045                 safe_free(current);
1046                 DEBUG(109,("deleted first value\n"));
1047                 return (True);
1048         }
1049
1050         current=previous->next;
1051                 
1052         while ( current!=NULL ) {
1053                 if (!strcmp(current->value, param->value) &&
1054                     strlen(current->value)==strlen(param->value) ) {
1055                         DEBUG(109,("deleting current value\n"));
1056                         previous->next=current->next;
1057                         safe_free(current->data);
1058                         safe_free(current);
1059                         DEBUG(109,("deleted current value\n"));
1060                         return(True);
1061                 }
1062                 
1063                 previous=previous->next;
1064                 current=current->next;
1065         }
1066         return (False);
1067 }
1068
1069 /****************************************************************************
1070  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
1071 ****************************************************************************/
1072 static void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
1073 {
1074         NT_PRINTER_PARAM *param = *param_ptr;
1075
1076         if(param == NULL)
1077                 return;
1078
1079         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
1080
1081         if(param->data)
1082                 safe_free(param->data);
1083
1084         safe_free(param);
1085         *param_ptr = NULL;
1086 }
1087
1088 /****************************************************************************
1089  Malloc and return an NT devicemode.
1090 ****************************************************************************/
1091
1092 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
1093 {
1094 /*
1095  * should I init this ones ???
1096         nt_devmode->devicename
1097 */
1098
1099         char adevice[32];
1100         NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
1101
1102         if (nt_devmode == NULL) {
1103                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
1104                 return NULL;
1105         }
1106
1107         ZERO_STRUCTP(nt_devmode);
1108
1109         snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, default_devicename);
1110         fstrcpy(nt_devmode->devicename, adevice);
1111         
1112         
1113         fstrcpy(nt_devmode->formname, "Letter");
1114
1115         nt_devmode->specversion      = 0x0401;
1116         nt_devmode->driverversion    = 0x0400;
1117         nt_devmode->size             = 0x00DC;
1118         nt_devmode->driverextra      = 0x0000;
1119         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY | 
1120                                        DEFAULTSOURCE | COPIES | SCALE | 
1121                                        PAPERSIZE | ORIENTATION;
1122         nt_devmode->orientation      = 1;
1123         nt_devmode->papersize        = PAPER_LETTER;
1124         nt_devmode->paperlength      = 0;
1125         nt_devmode->paperwidth       = 0;
1126         nt_devmode->scale            = 0x64;
1127         nt_devmode->copies           = 01;
1128         nt_devmode->defaultsource    = BIN_FORMSOURCE;
1129         nt_devmode->printquality     = 0x0258;
1130         nt_devmode->color            = COLOR_MONOCHROME;
1131         nt_devmode->duplex           = DUP_SIMPLEX;
1132         nt_devmode->yresolution      = 0;
1133         nt_devmode->ttoption         = TT_SUBDEV;
1134         nt_devmode->collate          = COLLATE_FALSE;
1135         nt_devmode->icmmethod        = 0;
1136         nt_devmode->icmintent        = 0;
1137         nt_devmode->mediatype        = 0;
1138         nt_devmode->dithertype       = 0;
1139
1140         /* non utilisés par un driver d'imprimante */
1141         nt_devmode->logpixels        = 0;
1142         nt_devmode->bitsperpel       = 0;
1143         nt_devmode->pelswidth        = 0;
1144         nt_devmode->pelsheight       = 0;
1145         nt_devmode->displayflags     = 0;
1146         nt_devmode->displayfrequency = 0;
1147         nt_devmode->reserved1        = 0;
1148         nt_devmode->reserved2        = 0;
1149         nt_devmode->panningwidth     = 0;
1150         nt_devmode->panningheight    = 0;
1151         
1152         nt_devmode->private=NULL;
1153
1154         return nt_devmode;
1155 }
1156
1157 /****************************************************************************
1158  Deepcopy an NT devicemode.
1159 ****************************************************************************/
1160
1161 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1162 {
1163         NT_DEVICEMODE *new_nt_devicemode = NULL;
1164
1165         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1166                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1167                 return NULL;
1168         }
1169
1170         new_nt_devicemode->private = NULL;
1171         if (nt_devicemode->private != NULL) {
1172                 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1173                         safe_free(new_nt_devicemode);
1174                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1175                         return NULL;
1176         }
1177         }
1178
1179         return new_nt_devicemode;
1180 }
1181
1182 /****************************************************************************
1183  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1184 ****************************************************************************/
1185
1186 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1187 {
1188         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1189
1190         if(nt_devmode == NULL)
1191                 return;
1192
1193         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
1194
1195         if(nt_devmode->private)
1196                 safe_free(nt_devmode->private);
1197
1198         safe_free(nt_devmode);
1199         *devmode_ptr = NULL;
1200 }
1201
1202 /****************************************************************************
1203  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
1204 ****************************************************************************/
1205 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
1206 {
1207         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
1208         NT_PRINTER_PARAM *param_ptr;
1209
1210         if(info == NULL)
1211                 return;
1212
1213         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
1214
1215         free_nt_devicemode(&info->devmode);
1216         free_sec_desc_buf(&info->secdesc_buf);
1217
1218         for(param_ptr = info->specific; param_ptr; ) {
1219                 NT_PRINTER_PARAM *tofree = param_ptr;
1220
1221                 param_ptr = param_ptr->next;
1222                 free_nt_printer_param(&tofree);
1223         }
1224
1225         safe_free(*info_ptr);
1226         *info_ptr = NULL;
1227 }
1228
1229
1230 /****************************************************************************
1231 ****************************************************************************/
1232 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
1233 {
1234         int len = 0;
1235         NT_DEVICEMODE devmode;
1236
1237         ZERO_STRUCT(devmode);
1238
1239         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
1240
1241         if (!*nt_devmode) return len;
1242
1243         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1244                           devmode.devicename,
1245                           devmode.formname,
1246
1247                           &devmode.specversion,
1248                           &devmode.driverversion,
1249                           &devmode.size,
1250                           &devmode.driverextra,
1251                           &devmode.orientation,
1252                           &devmode.papersize,
1253                           &devmode.paperlength,
1254                           &devmode.paperwidth,
1255                           &devmode.scale,
1256                           &devmode.copies,
1257                           &devmode.defaultsource,
1258                           &devmode.printquality,
1259                           &devmode.color,
1260                           &devmode.duplex,
1261                           &devmode.yresolution,
1262                           &devmode.ttoption,
1263                           &devmode.collate,
1264                           &devmode.logpixels,
1265                           
1266                           &devmode.fields,
1267                           &devmode.bitsperpel,
1268                           &devmode.pelswidth,
1269                           &devmode.pelsheight,
1270                           &devmode.displayflags,
1271                           &devmode.displayfrequency,
1272                           &devmode.icmmethod,
1273                           &devmode.icmintent,
1274                           &devmode.mediatype,
1275                           &devmode.dithertype,
1276                           &devmode.reserved1,
1277                           &devmode.reserved2,
1278                           &devmode.panningwidth,
1279                           &devmode.panningheight,
1280                           &devmode.private);
1281         
1282         if (devmode.private)            
1283                 len += tdb_unpack(buf+len, buflen-len, "B", &devmode.driverextra, &devmode.private);
1284
1285         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
1286
1287         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
1288         if (devmode.private)
1289                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
1290
1291         return len;
1292 }
1293
1294 /****************************************************************************
1295 ****************************************************************************/
1296 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
1297 {
1298         int len = 0;
1299         NT_PRINTER_PARAM param, *p;
1300
1301         *list = NULL;
1302
1303         while (1) {
1304                 len += tdb_unpack(buf+len, buflen-len, "p", &p);
1305                 if (!p) break;
1306
1307                 len += tdb_unpack(buf+len, buflen-len, "fdB",
1308                                   param.value, 
1309                                   &param.type, 
1310                                   &param.data_len,
1311                                   &param.data);
1312                 param.next = *list;
1313                 *list = memdup(&param, sizeof(param));
1314
1315                 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
1316         }
1317
1318         return len;
1319 }
1320
1321
1322 /****************************************************************************
1323 get a default printer info 2 struct
1324 ****************************************************************************/
1325 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1326 {
1327         extern pstring global_myname;
1328         int snum;
1329         NT_PRINTER_INFO_LEVEL_2 info;
1330
1331         ZERO_STRUCT(info);
1332
1333         snum = lp_servicenumber(sharename);
1334
1335         fstrcpy(info.servername, global_myname);
1336         fstrcpy(info.printername, sharename);
1337         fstrcpy(info.portname, sharename);
1338         fstrcpy(info.drivername, lp_printerdriver(snum));
1339         fstrcpy(info.comment, "");
1340         fstrcpy(info.printprocessor, "winprint");
1341         fstrcpy(info.datatype, "RAW");
1342
1343         info.attributes = PRINTER_ATTRIBUTE_SHARED   \
1344                          | PRINTER_ATTRIBUTE_LOCAL  \
1345                          | PRINTER_ATTRIBUTE_RAW_ONLY ;            /* attributes */
1346
1347         info.starttime = 0; /* Minutes since 12:00am GMT */
1348         info.untiltime = 0; /* Minutes since 12:00am GMT */
1349         info.priority = 1;
1350         info.default_priority = 1;
1351
1352         if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
1353                 goto fail;
1354
1355 #if 1
1356         if (!nt_printing_getsec(sharename, &info.secdesc_buf))
1357                 goto fail;
1358 #endif
1359
1360         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
1361         if (! *info_ptr) {
1362                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
1363                 goto fail;
1364         }
1365
1366         return (0);     
1367
1368   fail:
1369
1370         if (info.devmode)
1371                 free_nt_devicemode(&info.devmode);
1372         if (info.secdesc_buf)
1373                 free_sec_desc_buf(&info.secdesc_buf);
1374         return 2;
1375 }
1376
1377 /****************************************************************************
1378 ****************************************************************************/
1379 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1380 {
1381         pstring key;
1382         NT_PRINTER_INFO_LEVEL_2 info;
1383         int len = 0;
1384         TDB_DATA kbuf, dbuf;
1385                 
1386         ZERO_STRUCT(info);
1387
1388         slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
1389
1390         kbuf.dptr = key;
1391         kbuf.dsize = strlen(key)+1;
1392
1393         dbuf = tdb_fetch(tdb, kbuf);
1394 #if 1 /* JRATEST */
1395         if (!dbuf.dptr) return get_a_printer_2_default(info_ptr, sharename);
1396 #else
1397         if (!dbuf.dptr) return 1;
1398 #endif
1399
1400         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffffffff",
1401                         &info.attributes,
1402                         &info.priority,
1403                         &info.default_priority,
1404                         &info.starttime,
1405                         &info.untiltime,
1406                         &info.status,
1407                         &info.cjobs,
1408                         &info.averageppm,
1409                         &info.changeid,
1410                         &info.c_setprinter,
1411                         &info.setuptime,
1412                         info.servername,
1413                         info.printername,
1414                         info.sharename,
1415                         info.portname,
1416                         info.drivername,
1417                         info.comment,
1418                         info.location,
1419                         info.sepfile,
1420                         info.printprocessor,
1421                         info.datatype,
1422                         info.parameters);
1423
1424         /* Samba has to have shared raw drivers. */
1425         info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
1426
1427         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
1428         len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
1429
1430 #if 1 /* JRATEST */
1431         nt_printing_getsec(sharename, &info.secdesc_buf);
1432 #endif /* JRATEST */
1433
1434         safe_free(dbuf.dptr);
1435         *info_ptr=memdup(&info, sizeof(info));
1436
1437         DEBUG(9,("Unpacked printer [%s] running driver [%s]\n",
1438                  sharename, info.drivername));
1439
1440         
1441         return 0;       
1442 }
1443
1444 /****************************************************************************
1445 debugging function, dump at level 6 the struct in the logs
1446 ****************************************************************************/
1447 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1448 {
1449         uint32 success;
1450         NT_PRINTER_INFO_LEVEL_2 *info2;
1451         
1452         DEBUG(106,("Dumping printer at level [%d]\n", level));
1453         
1454         switch (level)
1455         {
1456                 case 2: 
1457                 {
1458                         if (printer.info_2 == NULL)
1459                                 success=5;
1460                         else
1461                         {
1462                                 info2=printer.info_2;
1463                         
1464                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
1465                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
1466                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
1467                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
1468                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
1469                                 DEBUGADD(106,("status:[%d]\n", info2->status));
1470                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
1471                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
1472                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
1473                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
1474                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
1475
1476                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
1477                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
1478                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
1479                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
1480                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
1481                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
1482                                 DEBUGADD(106,("location:[%s]\n", info2->location));
1483                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
1484                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
1485                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
1486                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
1487                                 success=0;
1488                         }
1489                         break;
1490                 }
1491                 default:
1492                         DEBUGADD(1,("Level not implemented\n"));
1493                         success=1;
1494                         break;
1495         }
1496         
1497         return (success);
1498 }
1499
1500 /*
1501  * The function below are the high level ones.
1502  * only those ones must be called from the spoolss code.
1503  * JFM.
1504  */
1505
1506
1507 /****************************************************************************
1508 ****************************************************************************/
1509 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1510 {
1511         uint32 success;
1512         
1513         dump_a_printer(printer, level); 
1514         
1515         switch (level)
1516         {
1517                 case 2: 
1518                 {
1519                         success=add_a_printer_2(printer.info_2);
1520                         break;
1521                 }
1522                 default:
1523                         success=1;
1524                         break;
1525         }
1526         
1527         return (success);
1528 }
1529
1530 /****************************************************************************
1531  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
1532 ****************************************************************************/
1533
1534 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
1535 {
1536         uint32 success;
1537         NT_PRINTER_INFO_LEVEL *printer = NULL;
1538         
1539         *pp_printer = NULL;
1540
1541         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
1542
1543         switch (level)
1544         {
1545                 case 2: 
1546                 {
1547                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
1548                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
1549                                 return 1;
1550                         }
1551                         ZERO_STRUCTP(printer);
1552                         success=get_a_printer_2(&printer->info_2, sharename);
1553                         if (success == 0) {
1554                                 dump_a_printer(*printer, level);
1555                                 *pp_printer = printer;
1556                         } else {
1557                                 safe_free(printer);
1558                         }
1559                         break;
1560                 }
1561                 default:
1562                         success=1;
1563                         break;
1564         }
1565         
1566         DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
1567
1568         return (success);
1569 }
1570
1571 /****************************************************************************
1572  Deletes a NT_PRINTER_INFO_LEVEL struct.
1573 ****************************************************************************/
1574
1575 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
1576 {
1577         uint32 success;
1578         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
1579
1580         DEBUG(104,("freeing a printer at level [%d]\n", level));
1581
1582         if (printer == NULL)
1583                 return 0;
1584         
1585         switch (level)
1586         {
1587                 case 2: 
1588                 {
1589                         if (printer->info_2 != NULL)
1590                         {
1591                                 free_nt_printer_info_level_2(&printer->info_2);
1592                                 success=0;
1593                         }
1594                         else
1595                         {
1596                                 success=4;
1597                         }
1598                         break;
1599                 }
1600                 default:
1601                         success=1;
1602                         break;
1603         }
1604
1605         safe_free(printer);
1606         *pp_printer = NULL;
1607         return (success);
1608 }
1609
1610 /****************************************************************************
1611 ****************************************************************************/
1612 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1613 {
1614         uint32 success;
1615         DEBUG(104,("adding a printer at level [%d]\n", level));
1616         dump_a_printer_driver(driver, level);
1617         
1618         switch (level)
1619         {
1620                 case 3: 
1621                 {
1622                         success=add_a_printer_driver_3(driver.info_3);
1623                         break;
1624                 }
1625
1626                 case 6: 
1627                 {
1628                         success=add_a_printer_driver_6(driver.info_6);
1629                         break;
1630                 }
1631                 default:
1632                         success=1;
1633                         break;
1634         }
1635         
1636         return (success);
1637 }
1638 /****************************************************************************
1639 ****************************************************************************/
1640 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, 
1641                             fstring printername, fstring architecture, uint32 version)
1642 {
1643         uint32 success;
1644         
1645         switch (level)
1646         {
1647                 case 3: 
1648                 {
1649                         success=get_a_printer_driver_3(&(driver->info_3), 
1650                                                        printername,
1651                                                        architecture, version);
1652                         break;
1653                 }
1654                 default:
1655                         success=1;
1656                         break;
1657         }
1658         
1659         if (success == 0) dump_a_printer_driver(*driver, level);
1660         return (success);
1661 }
1662
1663 /****************************************************************************
1664 ****************************************************************************/
1665 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1666 {
1667         uint32 success;
1668         
1669         switch (level)
1670         {
1671                 case 3: 
1672                 {
1673                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1674                         if (driver.info_3 != NULL)
1675                         {
1676                                 info3=driver.info_3;
1677                                 safe_free(info3->dependentfiles);
1678                                 ZERO_STRUCTP(info3);
1679                                 safe_free(info3);
1680                                 success=0;
1681                         }
1682                         else
1683                         {
1684                                 success=4;
1685                         }
1686                         break;
1687                 }
1688                 case 6: 
1689                 {
1690                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
1691                         if (driver.info_6 != NULL)
1692                         {
1693                                 info6=driver.info_6;
1694                                 safe_free(info6->dependentfiles);
1695                                 safe_free(info6->previousnames);
1696                                 ZERO_STRUCTP(info6);
1697                                 safe_free(info6);
1698                                 success=0;
1699                         }
1700                         else
1701                         {
1702                                 success=4;
1703                         }
1704                         break;
1705                 }
1706                 default:
1707                         success=1;
1708                         break;
1709         }
1710         return (success);
1711 }
1712
1713 /****************************************************************************
1714 ****************************************************************************/
1715 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
1716                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
1717 {
1718         /* right now that's enough ! */ 
1719         NT_PRINTER_PARAM *param;
1720         int i=0;
1721         
1722         param=printer.info_2->specific;
1723         
1724         while (param != NULL && i < param_index) {
1725                 param=param->next;
1726                 i++;
1727         }
1728         
1729         if (param == NULL)
1730                 return False;
1731
1732         /* exited because it exist */
1733         *type=param->type;              
1734         StrnCpy(value, param->value, sizeof(fstring)-1);
1735         *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1736         if(*data == NULL)
1737                 return False;
1738         ZERO_STRUCTP(*data);
1739         memcpy(*data, param->data, param->data_len);
1740         *len=param->data_len;
1741         return True;
1742 }
1743
1744 /****************************************************************************
1745 ****************************************************************************/
1746 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, 
1747                         fstring value, uint8 **data, uint32 *type, uint32 *len)
1748 {
1749         /* right now that's enough ! */ 
1750         NT_PRINTER_PARAM *param;
1751         
1752         DEBUG(105, ("get_specific_param\n"));
1753         
1754         param=printer.info_2->specific;
1755                 
1756         while (param != NULL)
1757         {
1758                 if ( !strcmp(value, param->value) 
1759                     && strlen(value)==strlen(param->value))
1760                         break;
1761                         
1762                 param=param->next;
1763         }
1764         
1765         DEBUG(106, ("found one param\n"));
1766         if (param != NULL)
1767         {
1768                 /* exited because it exist */
1769                 *type=param->type;      
1770                 
1771                 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1772                 if(*data == NULL)
1773                         return False;
1774                 memcpy(*data, param->data, param->data_len);
1775                 *len=param->data_len;
1776
1777                 DEBUG(106, ("exit of get_specific_param:true\n"));
1778                 return (True);
1779         }
1780         DEBUG(106, ("exit of get_specific_param:false\n"));
1781         return (False);
1782 }
1783
1784
1785 /****************************************************************************
1786 store a security desc for a printer
1787 ****************************************************************************/
1788 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
1789 {
1790         SEC_DESC_BUF *new_secdesc_ctr = NULL;
1791         SEC_DESC_BUF *old_secdesc_ctr = NULL;
1792         prs_struct ps;
1793         fstring key;
1794         uint32 status;
1795
1796         /* The old owner and group sids of the security descriptor are not
1797            present when new ACEs are added or removed by changing printer
1798            permissions through NT.  If they are NULL in the new security
1799            descriptor then copy them over from the old one. */
1800
1801         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
1802                 DOM_SID *owner_sid, *group_sid;
1803                 SEC_DESC *psd = NULL;
1804                 size_t size;
1805
1806                 nt_printing_getsec(printername, &old_secdesc_ctr);
1807
1808                 /* Pick out correct owner and group sids */
1809
1810                 owner_sid = secdesc_ctr->sec->owner_sid ?
1811                         secdesc_ctr->sec->owner_sid :
1812                         old_secdesc_ctr->sec->owner_sid;
1813
1814                 group_sid = secdesc_ctr->sec->grp_sid ?
1815                         secdesc_ctr->sec->grp_sid :
1816                         old_secdesc_ctr->sec->grp_sid;
1817
1818                 /* Make a deep copy of the security descriptor */
1819
1820                 psd = make_sec_desc(secdesc_ctr->sec->revision,
1821                                     secdesc_ctr->sec->type,
1822                                     owner_sid, group_sid,
1823                                     secdesc_ctr->sec->sacl,
1824                                     secdesc_ctr->sec->dacl,
1825                                     &size);
1826
1827                 new_secdesc_ctr = make_sec_desc_buf(size, psd);
1828
1829                 /* Free up memory */
1830
1831                 free_sec_desc(&psd);
1832                 free_sec_desc_buf(&old_secdesc_ctr);
1833         }
1834
1835         if (!new_secdesc_ctr) {
1836                 new_secdesc_ctr = secdesc_ctr;
1837         }
1838
1839         /* Store the security descriptor in a tdb */
1840
1841         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) + 
1842                  sizeof(SEC_DESC_BUF), 4, MARSHALL);
1843
1844         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr, 
1845                              &ps, 1)) {
1846                 status = ERROR_INVALID_FUNCTION;
1847                 goto out;
1848         }
1849
1850         slprintf(key, sizeof(key), "SECDESC/%s", printername);
1851
1852         if (tdb_prs_store(tdb, key, &ps)==0) {
1853                 status = 0;
1854         } else {
1855                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
1856                 status = ERROR_INVALID_FUNCTION;
1857         }
1858
1859         /* Free mallocated memory */
1860
1861  out:
1862         free_sec_desc_buf(&old_secdesc_ctr);
1863
1864         if (new_secdesc_ctr != secdesc_ctr) {
1865                 free_sec_desc_buf(&new_secdesc_ctr);
1866         }
1867
1868         prs_mem_free(&ps);
1869         return status;
1870 }
1871
1872 /****************************************************************************
1873  Construct a default security descriptor buffer for a printer.
1874 ****************************************************************************/
1875
1876 static SEC_DESC_BUF *construct_default_printer_sdb(void)
1877 {
1878         SEC_ACE ace;
1879         SEC_ACCESS sa;
1880         SEC_ACL *psa = NULL;
1881         SEC_DESC_BUF *sdb = NULL;
1882         SEC_DESC *psd = NULL;
1883         DOM_SID owner_sid;
1884         size_t sd_size;
1885         uint8 name_type;
1886
1887         /* Create an ACE where Everyone is allowed to print */
1888
1889         init_sec_access(&sa, PRINTER_ACE_PRINT);
1890         init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1891                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1892
1893
1894         /* Make the security descriptor owned by the Administrators group
1895            on the PDC of the domain. */
1896
1897         if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
1898                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
1899         } else {
1900
1901                 /* Backup plan - make printer owned by world.  This should
1902                    emulate a lanman printer as security settings can't be
1903                    changed. */
1904
1905                 sid_copy(&owner_sid, &global_sid_World);
1906         }
1907
1908         /* The ACL revision number in rpc_secdesc.h differs from the one
1909            created by NT when setting ACE entries in printer
1910            descriptors.  NT4 complains about the property being edited by a
1911            NT5 machine. */
1912
1913 #define NT4_ACL_REVISION 0x2
1914
1915         if ((psa = make_sec_acl(NT4_ACL_REVISION, 1, &ace)) != NULL) {
1916                 psd = make_sec_desc(SEC_DESC_REVISION, 
1917                                     SEC_DESC_SELF_RELATIVE | 
1918                                     SEC_DESC_DACL_PRESENT,
1919                                     &owner_sid, NULL,
1920                                     NULL, psa, &sd_size);
1921                 free_sec_acl(&psa);
1922         }
1923
1924         if (!psd) {
1925                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1926                 return NULL;
1927         }
1928
1929         sdb = make_sec_desc_buf(sd_size, psd);
1930
1931         DEBUG(4,("construct_default_printer_sdb: size = %u.\n", 
1932                  (unsigned int)sd_size));
1933
1934         free_sec_desc(&psd);
1935         return sdb;
1936 }
1937
1938 /****************************************************************************
1939  Get a security desc for a printer.
1940 ****************************************************************************/
1941
1942 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
1943 {
1944         prs_struct ps;
1945         fstring key;
1946
1947         /* Fetch security descriptor from tdb */
1948
1949         slprintf(key, sizeof(key), "SECDESC/%s", printername);
1950
1951         if (tdb_prs_fetch(tdb, key, &ps)!=0 ||
1952             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
1953
1954                 DEBUG(4,("using default secdesc for %s\n", printername));
1955
1956                 if (!(*secdesc_ctr = construct_default_printer_sdb()))
1957                         return False;
1958
1959                 return True;
1960         }
1961
1962         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
1963            this security descriptor has been created when winbindd was
1964            down.  Take ownership of security descriptor. */
1965
1966         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
1967                 DOM_SID owner_sid;
1968                 uint8 name_type;
1969
1970                 /* Change sd owner to workgroup administrator */
1971
1972                 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
1973                                         &name_type)) {
1974                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
1975                         SEC_DESC *psd = NULL;
1976                         size_t size;
1977
1978                         /* Create new sd */
1979
1980                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
1981
1982                         psd = make_sec_desc((*secdesc_ctr)->sec->revision,
1983                                             (*secdesc_ctr)->sec->type,
1984                                             &owner_sid,
1985                                             (*secdesc_ctr)->sec->grp_sid,
1986                                             (*secdesc_ctr)->sec->sacl,
1987                                             (*secdesc_ctr)->sec->dacl,
1988                                             &size);
1989
1990                         new_secdesc_ctr = make_sec_desc_buf(size, psd);
1991
1992                         free_sec_desc(&psd);
1993
1994                         /* Swap with other one */
1995
1996                         free_sec_desc_buf(secdesc_ctr);
1997                         *secdesc_ctr = new_secdesc_ctr;
1998
1999                         /* Set it */
2000
2001                         nt_printing_setsec(printername, *secdesc_ctr);
2002                 }
2003         }
2004
2005         prs_mem_free(&ps);
2006         return True;
2007 }
2008
2009 /* error code:
2010         0: everything OK
2011         1: level not implemented
2012         2: file doesn't exist
2013         3: can't allocate memory
2014         4: can't free memory
2015         5: non existant struct
2016 */
2017
2018 /*
2019         A printer and a printer driver are 2 different things.
2020         NT manages them separatelly, Samba does the same.
2021         Why ? Simply because it's easier and it makes sense !
2022         
2023         Now explanation: You have 3 printers behind your samba server,
2024         2 of them are the same make and model (laser A and B). But laser B 
2025         has an 3000 sheet feeder and laser A doesn't such an option.
2026         Your third printer is an old dot-matrix model for the accounting :-).
2027         
2028         If the /usr/local/samba/lib directory (default dir), you will have
2029         5 files to describe all of this.
2030         
2031         3 files for the printers (1 by printer):
2032                 NTprinter_laser A
2033                 NTprinter_laser B
2034                 NTprinter_accounting
2035         2 files for the drivers (1 for the laser and 1 for the dot matrix)
2036                 NTdriver_printer model X
2037                 NTdriver_printer model Y
2038
2039 jfm: I should use this comment for the text file to explain 
2040         same thing for the forms BTW.
2041         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2042
2043 */
2044
2045 /* Check a user has permissions to perform the given operation */
2046
2047 BOOL print_access_check(struct current_user *user, int snum,
2048                         uint32 required_access)
2049 {
2050         SEC_DESC_BUF *secdesc = NULL;
2051         uint32 access_granted, status;
2052         BOOL result;
2053         char *pname;
2054         int i;
2055         
2056         /* Get printer name */
2057
2058         pname = PRINTERNAME(snum);
2059         if (!pname || !*pname) pname = SERVICE(snum);
2060
2061         /* Get printer security descriptor */
2062
2063         nt_printing_getsec(pname, &secdesc);
2064
2065         /* The ACE for Full Control in a printer security descriptor
2066            doesn't seem to map properly to the access checking model.  For
2067            it to work properly it should be the logical OR of all the other
2068            values, i.e PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT.
2069            This would cause the access check to simply fall out when we
2070            check against any subset of these bits.  To get things to work,
2071            change every ACE mask of PRINTER_ACE_FULL_CONTROL to 
2072            PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before
2073            performing the access check.  I'm sure there is a better way to
2074            do this! */
2075
2076         if (secdesc && secdesc->sec && secdesc->sec->dacl &&
2077             secdesc->sec->dacl->ace) {
2078                 for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
2079                         if (secdesc->sec->dacl->ace[i].info.mask ==
2080                             PRINTER_ACE_FULL_CONTROL) {
2081                                 secdesc->sec->dacl->ace[i].info.mask =
2082                                         PRINTER_ACE_MANAGE_DOCUMENTS | 
2083                                         PRINTER_ACE_PRINT;
2084                         }
2085                 }
2086         }
2087
2088         /* Check access */
2089
2090         result = se_access_check(secdesc->sec, user, required_access, 
2091                                  &access_granted, &status);
2092
2093         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
2094
2095         /* Free mallocated memory */
2096
2097         free_sec_desc_buf(&secdesc);
2098
2099         return result;
2100 }