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