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