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