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