Sync-up with appliance-head printing code.
[samba.git] / source3 / printing / nt_printing.c
1 #define OLD_NTDOMAIN 1
2 /*
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-2000,
7  *  Copyright (C) Jean François Micouleau      1998-2000.
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include "includes.h"
25
26 extern int DEBUGLEVEL;
27 extern pstring global_myname;
28 extern DOM_SID global_sid_World;
29
30 static TDB_CONTEXT *tdb; /* used for driver files */
31
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35
36 #define DATABASE_VERSION 1
37
38 /* We need 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; n++) {
167                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
168                         DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
169                         update=True;
170                         break;
171                 }
172         }
173
174         if (update==False) {
175                 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
176                         return False;
177                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
178                 (*count)++;
179         }
180         
181         (*list)[n].flag=form->flags;
182         (*list)[n].width=form->size_x;
183         (*list)[n].length=form->size_y;
184         (*list)[n].left=form->left;
185         (*list)[n].top=form->top;
186         (*list)[n].right=form->right;
187         (*list)[n].bottom=form->bottom;
188
189         return True;
190 }
191
192 /****************************************************************************
193  delete a named form struct
194 ****************************************************************************/
195 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
196 {
197         pstring key;
198         TDB_DATA kbuf;
199         int n=0;
200         fstring form_name;
201
202         *ret = 0;
203
204         if (*count == 1) {
205                 /*
206                  * Don't delete the last form (no empty lists).
207                  * CHECKME ! Is this correct ? JRA.
208                  */
209                 *ret = ERROR_INVALID_PARAMETER;
210                 return False;
211         }
212
213         unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
214
215         for (n=0; n<*count; n++) {
216                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
217                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
218                         break;
219                 }
220         }
221
222         if (n == *count) {
223                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
224                 *ret = ERROR_INVALID_PARAMETER;
225                 return False;
226         }
227
228         slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
229         kbuf.dsize = strlen(key)+1;
230         kbuf.dptr = key;
231         if (tdb_delete(tdb, kbuf) != 0) {
232                 *ret = ERROR_NOT_ENOUGH_MEMORY;
233                 return False;
234         }
235
236         return True;
237 }
238
239 /****************************************************************************
240 update a form struct
241 ****************************************************************************/
242 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
243 {
244         int n=0;
245         fstring form_name;
246         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
247
248         DEBUG(106, ("[%s]\n", form_name));
249         for (n=0; n<count; n++)
250         {
251                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
252                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
253                         break;
254         }
255
256         if (n==count) return;
257
258         (*list)[n].flag=form->flags;
259         (*list)[n].width=form->size_x;
260         (*list)[n].length=form->size_y;
261         (*list)[n].left=form->left;
262         (*list)[n].top=form->top;
263         (*list)[n].right=form->right;
264         (*list)[n].bottom=form->bottom;
265 }
266
267 /****************************************************************************
268 get the nt drivers list
269
270 traverse the database and look-up the matching names
271 ****************************************************************************/
272 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
273 {
274         int total=0;
275         fstring short_archi;
276         pstring key;
277         TDB_DATA kbuf, newkey;
278
279         get_short_archi(short_archi, architecture);
280         slprintf(key, sizeof(key), "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
281
282         for (kbuf = tdb_firstkey(tdb);
283              kbuf.dptr;
284              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
285                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
286                 
287                 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
288                         return -1;
289
290                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
291                 total++;
292         }
293
294         return(total);
295 }
296
297 /****************************************************************************
298 function to do the mapping between the long architecture name and
299 the short one.
300 ****************************************************************************/
301 BOOL get_short_archi(char *short_archi, char *long_archi)
302 {
303         struct table {
304                 char *long_archi;
305                 char *short_archi;
306         };
307         
308         struct table archi_table[]=
309         {
310                 {"Windows 4.0",          "WIN40"    },
311                 {"Windows NT x86",       "W32X86"   },
312                 {"Windows NT R4000",     "W32MIPS"  },
313                 {"Windows NT Alpha_AXP", "W32ALPHA" },
314                 {"Windows NT PowerPC",   "W32PPC"   },
315                 {NULL,                   ""         }
316         };
317         
318         int i=-1;
319
320         DEBUG(107,("Getting architecture dependant directory\n"));
321         do {
322                 i++;
323         } while ( (archi_table[i].long_archi!=NULL ) &&
324                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
325
326         if (archi_table[i].long_archi==NULL) {
327                 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
328                 return FALSE;
329         }
330
331         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
332
333         DEBUGADD(108,("index: [%d]\n", i));
334         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
335         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
336         
337         return TRUE;
338 }
339
340 /****************************************************************************
341 Determine the correct cVersion associated with an architecture and driver
342 ****************************************************************************/
343 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
344                                                                    struct current_user *user, uint32 *perr)
345 {
346         int               cversion;
347         int               access_mode;
348         int               action;
349         int               ecode;
350         char              buf[PE_HEADER_SIZE];
351         ssize_t           byte_count;
352         pstring           driverpath;
353         fstring           user_name;
354         fstring           null_pw;
355         files_struct      *fsp = NULL;
356         BOOL              bad_path;
357         SMB_STRUCT_STAT   st;
358         struct passwd *pass;
359         connection_struct *conn;
360
361         ZERO_STRUCT(st);
362
363         /* If architecture is Windows 95/98, the version is always 0. */
364         if (strcmp(architecture, "WIN40") == 0) {
365                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
366                 return 0;
367         }
368
369         become_root();
370         pass = getpwuid(user->uid);
371         if(pass == NULL) {
372                 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
373                                 (unsigned int)user->uid ));
374                 unbecome_root();
375                 *perr = ERROR_ACCESS_DENIED;
376                 return -1;
377         }
378         unbecome_root();
379
380         /* connect to the print$ share under the same account as the user connected
381          * to the rpc pipe */   
382         fstrcpy(user_name, pass->pw_name );
383         DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
384
385         /* Null password is ok - we are already an authenticated user... */
386         *null_pw = '\0';
387         conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
388
389         if (conn == NULL) {
390                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
391                 *perr = (uint32)ecode;
392                 return -1;
393         }
394
395         /* Save who we are - we are temporarily becoming the connection user. */
396         push_sec_ctx();
397
398         if (!become_user(conn, conn->vuid)) {
399                 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
400                 *perr = ERROR_ACCESS_DENIED;
401                 pop_sec_ctx();
402                 return -1;
403         }
404
405         /* Open the driver file (Portable Executable format) and determine the
406          * deriver the cversion. */
407         slprintf(driverpath, sizeof(driverpath), "%s/%s", architecture, driverpath_in);
408
409         unix_convert(driverpath,conn,NULL,&bad_path,&st);
410
411         fsp = open_file_shared(conn, driverpath, &st,
412                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
413                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
414                                                    0, 0, &access_mode, &action);
415         if (!fsp) {
416                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
417                                 driverpath, errno));
418                 *perr = ERROR_ACCESS_DENIED;
419                 goto error_exit;
420         }
421
422         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
423                 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
424                                 driverpath, byte_count));
425                 *perr = NT_STATUS_FILE_INVALID;
426                 goto error_exit;
427         }
428
429         /* Is this really a DOS header? */
430         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
431                 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
432                                 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
433                 *perr = NT_STATUS_FILE_INVALID;
434                 goto error_exit;
435         }
436
437         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
438         if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
439                 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
440                                 driverpath, errno));
441                 *perr = NT_STATUS_FILE_INVALID;
442                 goto error_exit;
443         }
444
445         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
446                 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
447                                 driverpath, byte_count));
448                 *perr = NT_STATUS_FILE_INVALID;
449                 goto error_exit;
450         }
451
452         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
453         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
454                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
455
456                         switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
457                                 case 4: cversion = 2; break;    /* Win NT 4 */
458                                 case 5: cversion = 3; break;    /* Win 2000 */
459                                 default:
460                                         DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
461                                                         driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
462                                         *perr = NT_STATUS_FILE_INVALID;
463                                         goto error_exit;
464                         }
465                 } else {
466                         DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
467                                         driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
468                         *perr = NT_STATUS_FILE_INVALID;
469                         goto error_exit;
470                 }
471
472         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
473                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
474
475                         switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
476                                 case 3: cversion = 0; break;    /* Win 3.x / Win 9x / Win ME */
477                         /*      case ?: cversion = 1; break;*/  /* Win NT 3.51 ... needs research JRR */
478                                 default:
479                                         DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
480                                                         driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
481                                         *perr = NT_STATUS_FILE_INVALID;
482                                         goto error_exit;
483                         }
484                 } else {
485                         DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
486                                         driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
487                         *perr = NT_STATUS_FILE_INVALID;
488                         goto error_exit;
489                 }
490
491         } else {
492                 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
493                                 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
494                 *perr = NT_STATUS_FILE_INVALID;
495                 goto error_exit;
496         }
497
498         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
499                         driverpath, cversion));
500
501         fsp->conn->vfs_ops.close(fsp, fsp->fd);
502         file_free(fsp);
503         close_cnum(conn, user->vuid);
504         pop_sec_ctx();
505         return cversion;
506
507
508         error_exit:
509                 if(fsp) {
510                         if(fsp->fd != -1)
511                                 fsp->conn->vfs_ops.close(fsp, fsp->fd);
512                         file_free(fsp);
513                 }
514
515                 close_cnum(conn, user->vuid);
516                 pop_sec_ctx();
517                 return -1;
518 }
519
520 /****************************************************************************
521 ****************************************************************************/
522 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
523                                                                                          struct current_user *user)
524 {
525         fstring architecture;
526         fstring new_name;
527         char *p;
528         int i;
529         uint32 err;
530
531         /* clean up the driver name.
532          * we can get .\driver.dll
533          * or worse c:\windows\system\driver.dll !
534          */
535         /* using an intermediate string to not have overlaping memcpy()'s */
536         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
537                 fstrcpy(new_name, p+1);
538                 fstrcpy(driver->driverpath, new_name);
539         }
540
541         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
542                 fstrcpy(new_name, p+1);
543                 fstrcpy(driver->datafile, new_name);
544         }
545
546         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
547                 fstrcpy(new_name, p+1);
548                 fstrcpy(driver->configfile, new_name);
549         }
550
551         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
552                 fstrcpy(new_name, p+1);
553                 fstrcpy(driver->helpfile, new_name);
554         }
555
556         if (driver->dependentfiles) {
557                 for (i=0; *driver->dependentfiles[i]; i++) {
558                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
559                                 fstrcpy(new_name, p+1);
560                                 fstrcpy(driver->dependentfiles[i], new_name);
561                         }
562                 }
563         }
564
565         get_short_archi(architecture, driver->environment);
566         
567         /* jfm:7/16/2000 the client always sends the cversion=0.
568          * The server should check which version the driver is by reading
569          * the PE header of driver->driverpath.
570          *
571          * For Windows 95/98 the version is 0 (so the value sent is correct)
572          * For Windows NT (the architecture doesn't matter)
573          *      NT 3.1: cversion=0
574          *      NT 3.5/3.51: cversion=1
575          *      NT 4: cversion=2
576          *      NT2K: cversion=3
577          */
578         if ((driver->cversion = get_correct_cversion( architecture,
579                                                                         driver->driverpath, user, &err)) == -1)
580                 return err;
581
582         return NT_STATUS_NO_PROBLEMO;
583 }
584         
585 /****************************************************************************
586 ****************************************************************************/
587 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
588                                                                                          struct current_user *user)
589 {
590         fstring architecture;
591         fstring new_name;
592         char *p;
593         int i;
594         uint32 err;
595
596         /* clean up the driver name.
597          * we can get .\driver.dll
598          * or worse c:\windows\system\driver.dll !
599          */
600         /* using an intermediate string to not have overlaping memcpy()'s */
601         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
602                 fstrcpy(new_name, p+1);
603                 fstrcpy(driver->driverpath, new_name);
604         }
605
606         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
607                 fstrcpy(new_name, p+1);
608                 fstrcpy(driver->datafile, new_name);
609         }
610
611         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
612                 fstrcpy(new_name, p+1);
613                 fstrcpy(driver->configfile, new_name);
614         }
615
616         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
617                 fstrcpy(new_name, p+1);
618                 fstrcpy(driver->helpfile, new_name);
619         }
620
621         if (driver->dependentfiles) {
622                 for (i=0; *driver->dependentfiles[i]; i++) {
623                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
624                                 fstrcpy(new_name, p+1);
625                                 fstrcpy(driver->dependentfiles[i], new_name);
626                         }
627                 }
628         }
629
630         get_short_archi(architecture, driver->environment);
631
632         /* jfm:7/16/2000 the client always sends the cversion=0.
633          * The server should check which version the driver is by reading
634          * the PE header of driver->driverpath.
635          *
636          * For Windows 95/98 the version is 0 (so the value sent is correct)
637          * For Windows NT (the architecture doesn't matter)
638          *      NT 3.1: cversion=0
639          *      NT 3.5/3.51: cversion=1
640          *      NT 4: cversion=2
641          *      NT2K: cversion=3
642          */
643         if ((driver->version = get_correct_cversion(architecture,
644                                                                         driver->driverpath, user, &err)) == -1)
645                 return err;
646
647         return NT_STATUS_NO_PROBLEMO;
648 }
649
650 /****************************************************************************
651 ****************************************************************************/
652 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
653                                                           uint32 level, struct current_user *user)
654 {
655         switch (level) {
656                 case 3:
657                 {
658                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
659                         driver=driver_abstract.info_3;
660                         return clean_up_driver_struct_level_3(driver, user);
661                 }
662                 case 6:
663                 {
664                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
665                         driver=driver_abstract.info_6;
666                         return clean_up_driver_struct_level_6(driver, user);
667                 }
668                 default:
669                         return ERROR_INVALID_PARAMETER;
670         }
671 }
672
673 /****************************************************************************
674  This function sucks and should be replaced. JRA.
675 ****************************************************************************/
676
677 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
678 {
679     dst->cversion  = src->version;
680
681     fstrcpy( dst->name, src->name);
682     fstrcpy( dst->environment, src->environment);
683     fstrcpy( dst->driverpath, src->driverpath);
684     fstrcpy( dst->datafile, src->datafile);
685     fstrcpy( dst->configfile, src->configfile);
686     fstrcpy( dst->helpfile, src->helpfile);
687     fstrcpy( dst->monitorname, src->monitorname);
688     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
689     dst->dependentfiles = src->dependentfiles;
690 }
691
692 #if 0 /* Debugging function */
693
694 static char* ffmt(unsigned char *c){
695         int i;
696         static char ffmt_str[17];
697
698         for (i=0; i<16; i++) {
699                 if ((c[i] < ' ') || (c[i] > '~'))
700                         ffmt_str[i]='.';
701                 else
702                         ffmt_str[i]=c[i];
703         }
704     ffmt_str[16]='\0';
705         return ffmt_str;
706 }
707
708 #endif
709
710 /****************************************************************************
711 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
712 There are two case to be covered here: PE (Portable Executable) and NE (New
713 Executable) files. Both files support the same INFO structure, but PE files
714 store the signature in unicode, and NE files store it as !unicode.
715 ****************************************************************************/
716 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
717                                                          uint32 *minor)
718 {
719         int     i;
720         char    *buf;
721         ssize_t byte_count;
722
723         if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
724                 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
725                                 fname, PE_HEADER_SIZE));
726                 goto error_exit;
727         }
728
729         /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
730         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
731                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
732                                 fname, byte_count));
733                 goto no_version_info;
734         }
735
736         /* Is this really a DOS header? */
737         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
738                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
739                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
740                 goto no_version_info;
741         }
742
743         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
744         if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
745                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
746                                 fname, errno));
747                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
748                 goto no_version_info;
749         }
750
751         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
752                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
753                                 fname, byte_count));
754                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
755                 goto no_version_info;
756         }
757
758         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
759         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
760                 int num_sections;
761                 int section_table_bytes;
762                 
763                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
764                         DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
765                                         fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
766                         /* At this point, we assume the file is in error. It still could be somthing
767                          * else besides a PE file, but it unlikely at this point.
768                          */
769                         goto error_exit;
770                 }
771
772                 /* get the section table */
773                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
774                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
775                 free(buf);
776                 if ((buf=malloc(section_table_bytes)) == NULL) {
777                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
778                                         fname, section_table_bytes));
779                         goto error_exit;
780                 }
781
782                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
783                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
784                                         fname, byte_count));
785                         goto error_exit;
786                 }
787
788                 /* Iterate the section table looking for the resource section ".rsrc" */
789                 for (i = 0; i < num_sections; i++) {
790                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
791
792                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
793                                 int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
794                                 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
795
796                                 free(buf);
797                                 if ((buf=malloc(section_bytes)) == NULL) {
798                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
799                                                         fname, section_bytes));
800                                         goto error_exit;
801                                 }
802
803                                 /* Seek to the start of the .rsrc section info */
804                                 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
805                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
806                                                         fname, errno));
807                                         goto error_exit;
808                                 }
809
810                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
811                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
812                                                         fname, byte_count));
813                                         goto error_exit;
814                                 }
815
816                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
817                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
818                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
819                                                 /* Align to next long address */
820                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
821
822                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
823                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
824                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
825                                                         
826                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
827                                                                           fname, *major, *minor,
828                                                                           (*major>>16)&0xffff, *major&0xffff,
829                                                                           (*minor>>16)&0xffff, *minor&0xffff));
830                                                         free(buf);
831                                                         return True;
832                                                 }
833                                         }
834                                 }
835                         }
836                 }
837
838                 /* Version info not found, fall back to origin date/time */
839                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
840                 free(buf);
841                 return False;
842
843         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
844                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
845                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
846                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
847                         /* At this point, we assume the file is in error. It still could be somthing
848                          * else besides a NE file, but it unlikely at this point. */
849                         goto error_exit;
850                 }
851
852                 /* Allocate a bit more space to speed up things */
853                 free(buf);
854                 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
855                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
856                                         fname, PE_HEADER_SIZE));
857                         goto error_exit;
858                 }
859
860                 /* This is a HACK! I got tired of trying to sort through the messy
861                  * 'NE' file format. If anyone wants to clean this up please have at
862                  * it, but this works. 'NE' files will eventually fade away. JRR */
863                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
864                         /* Cover case that should not occur in a well formed 'NE' .dll file */
865                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
866
867                         for(i=0; i<byte_count; i++) {
868                                 /* Fast skip past data that can't possibly match */
869                                 if (buf[i] != 'V') continue;
870
871                                 /* Potential match data crosses buf boundry, move it to beginning
872                                  * of buf, and fill the buf with as much as it will hold. */
873                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
874                                         int bc;
875
876                                         memcpy(buf, &buf[i], byte_count-i);
877                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
878                                                                    (byte_count-i))) < 0) {
879
880                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
881                                                                  fname, errno));
882                                                 goto error_exit;
883                                         }
884
885                                         byte_count = bc + (byte_count - i);
886                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
887
888                                         i = 0;
889                                 }
890
891                                 /* Check that the full signature string and the magic number that
892                                  * follows exist (not a perfect solution, but the chances that this
893                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
894                                  * twice, as it is simpler to read the code. */
895                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
896                                         /* Compute skip alignment to next long address */
897                                         int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
898                                                                  sizeof(VS_SIGNATURE)) & 3;
899                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
900
901                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
902                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
903                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
904                                                           fname, *major, *minor,
905                                                           (*major>>16)&0xffff, *major&0xffff,
906                                                           (*minor>>16)&0xffff, *minor&0xffff));
907                                         free(buf);
908                                         return True;
909                                 }
910                         }
911                 }
912
913                 /* Version info not found, fall back to origin date/time */
914                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
915                 free(buf);
916                 return False;
917
918         } else
919                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
920                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
921                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
922
923         no_version_info:
924                 free(buf);
925                 return False;
926
927         error_exit:
928                 free(buf);
929                 return -1;
930 }
931
932 /****************************************************************************
933 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
934 share one or more files. During the MS installation process files are checked
935 to insure that only a newer version of a shared file is installed over an
936 older version. There are several possibilities for this comparison. If there
937 is no previous version, the new one is newer (obviously). If either file is
938 missing the version info structure, compare the creation date (on Unix use
939 the modification date). Otherwise chose the numerically larger version number.
940 ****************************************************************************/
941 static int file_version_is_newer(connection_struct *conn, fstring new_file,
942                                                                 fstring old_file)
943 {
944         BOOL   use_version = True;
945         pstring filepath;
946
947         uint32 new_major;
948         uint32 new_minor;
949         time_t new_create_time;
950
951         uint32 old_major;
952         uint32 old_minor;
953         time_t old_create_time;
954
955         int access_mode;
956         int action;
957         files_struct    *fsp = NULL;
958         SMB_STRUCT_STAT st;
959         SMB_STRUCT_STAT stat_buf;
960         BOOL bad_path;
961
962         ZERO_STRUCT(st);
963         ZERO_STRUCT(stat_buf);
964         new_create_time = (time_t)0;
965         old_create_time = (time_t)0;
966
967         /* Get file version info (if available) for previous file (if it exists) */
968         pstrcpy(filepath, old_file);
969
970         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
971
972         fsp = open_file_shared(conn, filepath, &stat_buf,
973                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
974                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
975                                                    0, 0, &access_mode, &action);
976         if (!fsp) {
977                 /* Old file not found, so by definition new file is in fact newer */
978                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
979                                 filepath, errno));
980                 return True;
981
982         } else {
983                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
984                 if (ret == -1) goto error_exit;
985
986                 if (!ret) {
987                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
988                                          old_file));
989                         use_version = False;
990                         if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
991                         old_create_time = st.st_mtime;
992                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
993                 }
994         }
995         fsp->conn->vfs_ops.close(fsp, fsp->fd);
996         file_free(fsp);
997
998
999         /* Get file version info (if available) for new file */
1000         pstrcpy(filepath, new_file);
1001         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1002
1003         fsp = open_file_shared(conn, filepath, &stat_buf,
1004                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
1005                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1006                                                    0, 0, &access_mode, &action);
1007         if (!fsp) {
1008                 /* New file not found, this shouldn't occur if the caller did its job */
1009                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1010                                 filepath, errno));
1011                 goto error_exit;
1012
1013         } else {
1014                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1015                 if (ret == -1) goto error_exit;
1016
1017                 if (!ret) {
1018                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1019                                          new_file));
1020                         use_version = False;
1021                         if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1022                         new_create_time = st.st_mtime;
1023                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1024                 }
1025         }
1026         fsp->conn->vfs_ops.close(fsp, fsp->fd);
1027         file_free(fsp);
1028
1029         if (use_version) {
1030                 /* Compare versions and choose the larger version number */
1031                 if (new_major > old_major ||
1032                         (new_major == old_major && new_minor > old_minor)) {
1033                         
1034                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1035                         return True;
1036                 }
1037                 else {
1038                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1039                         return False;
1040                 }
1041
1042         } else {
1043                 /* Compare modification time/dates and choose the newest time/date */
1044                 if (new_create_time > old_create_time) {
1045                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1046                         return True;
1047                 }
1048                 else {
1049                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1050                         return False;
1051                 }
1052         }
1053
1054         error_exit:
1055                 if(fsp) {
1056                         file_free(fsp);
1057                         if(fsp->fd != -1)
1058                                 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1059                 }
1060                 return -1;
1061 }
1062
1063 /****************************************************************************
1064 ****************************************************************************/
1065 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1066 {
1067         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1068         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1069         fstring architecture;
1070         pstring new_dir;
1071         pstring old_name;
1072         pstring new_name;
1073         fstring user_name;
1074         fstring null_pw;
1075         connection_struct *conn;
1076         pstring inbuf;
1077         pstring outbuf;
1078         struct passwd *pass;
1079         int ecode;
1080         int ver = 0;
1081         int outsize = 0;
1082         int i;
1083
1084         *perr = 0;
1085         memset(inbuf, '\0', sizeof(inbuf));
1086         memset(outbuf, '\0', sizeof(outbuf));
1087
1088         if (level==3)
1089                 driver=driver_abstract.info_3;
1090         else if (level==6) {
1091                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1092                 driver = &converted_driver;
1093         } else {
1094                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1095                 return False;
1096         }
1097
1098         get_short_archi(architecture, driver->environment);
1099
1100         become_root();
1101         pass = getpwuid(user->uid);
1102         if(pass == NULL) {
1103                 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1104                                 (unsigned int)user->uid ));
1105                 unbecome_root();
1106                 return False;
1107         }
1108         unbecome_root();
1109
1110         /* connect to the print$ share under the same account as the user connected to the rpc pipe */  
1111         fstrcpy(user_name, pass->pw_name );
1112         DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1113
1114         /* Null password is ok - we are already an authenticated user... */
1115         *null_pw = '\0';
1116         conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1117
1118         if (conn == NULL) {
1119                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1120                 *perr = (uint32)ecode;
1121                 return False;
1122         }
1123
1124         /*
1125          * Save who we are - we are temporarily becoming the connection user.
1126          */
1127
1128         push_sec_ctx();
1129
1130         if (!become_user(conn, conn->vuid)) {
1131                 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1132                 pop_sec_ctx();
1133                 return False;
1134         }
1135
1136         /*
1137          * make the directories version and version\driver_name
1138          * under the architecture directory.
1139          */
1140         DEBUG(5,("Creating first directory\n"));
1141         slprintf(new_dir, sizeof(new_dir), "%s/%d", architecture, driver->cversion);
1142         mkdir_internal(conn, inbuf, outbuf, new_dir);
1143
1144         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1145          * listed for this driver which has already been moved, skip it (note:
1146          * drivers may list the same file name several times. Then check if the
1147          * file already exists in archi\cversion\, if so, check that the version
1148          * info (or time stamps if version info is unavailable) is newer (or the
1149          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1150          * Otherwise, delete the file.
1151          *
1152          * If a file is not moved to archi\cversion\ because of an error, all the
1153          * rest of the 'unmoved' driver files are removed from archi\. If one or
1154          * more of the driver's files was already moved to archi\cversion\, it
1155          * potentially leaves the driver in a partially updated state. Version
1156          * trauma will most likely occur if an client attempts to use any printer
1157          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1158          * done is appropriate... later JRR
1159          */
1160
1161         DEBUG(5,("Moving files now !\n"));
1162
1163         if (driver->driverpath && strlen(driver->driverpath)) {
1164                 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->driverpath);        
1165                 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->driverpath);     
1166                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1167                         if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1168                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1169                                                 new_name, old_name));
1170                                 *perr = (uint32)SVAL(outbuf,smb_err);
1171                                 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1172                                 ver = -1;
1173                         }
1174                 }
1175                 else
1176                         unlink_internals(conn, inbuf, outbuf, 0, new_name);
1177         }
1178
1179         if (driver->datafile && strlen(driver->datafile)) {
1180                 if (!strequal(driver->datafile, driver->driverpath)) {
1181                         slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->datafile);  
1182                         slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->datafile);       
1183                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1184                                 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1185                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1186                                                         new_name, old_name));
1187                                         *perr = (uint32)SVAL(outbuf,smb_err);
1188                                         unlink_internals(conn, inbuf, outbuf, 0, new_name);
1189                                         ver = -1;
1190                                 }
1191                         }
1192                         else
1193                                 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1194                 }
1195         }
1196
1197         if (driver->configfile && strlen(driver->configfile)) {
1198                 if (!strequal(driver->configfile, driver->driverpath) &&
1199                         !strequal(driver->configfile, driver->datafile)) {
1200                         slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->configfile);        
1201                         slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->configfile);     
1202                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1203                                 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1204                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1205                                                         new_name, old_name));
1206                                         *perr = (uint32)SVAL(outbuf,smb_err);
1207                                         unlink_internals(conn, inbuf, outbuf, 0, new_name);
1208                                         ver = -1;
1209                                 }
1210                         }
1211                         else
1212                                 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1213                 }
1214         }
1215
1216         if (driver->helpfile && strlen(driver->helpfile)) {
1217                 if (!strequal(driver->helpfile, driver->driverpath) &&
1218                         !strequal(driver->helpfile, driver->datafile) &&
1219                         !strequal(driver->helpfile, driver->configfile)) {
1220                         slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->helpfile);  
1221                         slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->helpfile);       
1222                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1223                                 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1224                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1225                                                         new_name, old_name));
1226                                         *perr = (uint32)SVAL(outbuf,smb_err);
1227                                         unlink_internals(conn, inbuf, outbuf, 0, new_name);
1228                                         ver = -1;
1229                                 }
1230                         }
1231                         else
1232                                 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1233                 }
1234         }
1235
1236         if (driver->dependentfiles) {
1237                 for (i=0; *driver->dependentfiles[i]; i++) {
1238                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1239                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1240                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1241                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1242                                 int j;
1243                                 for (j=0; j < i; j++) {
1244                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1245                                                 goto NextDriver;
1246                                         }
1247                                 }
1248
1249                                 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->dependentfiles[i]); 
1250                                 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->dependentfiles[i]);      
1251                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1252                                         if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1253                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1254                                                                 new_name, old_name));
1255                                                 *perr = (uint32)SVAL(outbuf,smb_err);
1256                                                 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1257                                                 ver = -1;
1258                                         }
1259                                 }
1260                                 else
1261                                         unlink_internals(conn, inbuf, outbuf, 0, new_name);
1262                         }
1263                 NextDriver: ;
1264                 }
1265         }
1266
1267         close_cnum(conn, user->vuid);
1268         pop_sec_ctx();
1269
1270         return ver == -1 ? False : True;
1271 }
1272
1273 /****************************************************************************
1274 ****************************************************************************/
1275 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1276 {
1277         int len, buflen;
1278         fstring architecture;
1279         pstring directory;
1280         pstring temp_name;
1281         pstring key;
1282         char *buf;
1283         int i, ret;
1284         TDB_DATA kbuf, dbuf;
1285
1286         get_short_archi(architecture, driver->environment);
1287
1288         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1289          * \\server is added in the rpc server layer.
1290          * It does make sense to NOT store the server's name in the printer TDB.
1291          */
1292
1293         slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
1294
1295         
1296         fstrcpy(temp_name, driver->driverpath);
1297         slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
1298
1299         fstrcpy(temp_name, driver->datafile);
1300         slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
1301
1302         fstrcpy(temp_name, driver->configfile);
1303         slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
1304
1305         fstrcpy(temp_name, driver->helpfile);
1306         slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
1307
1308         if (driver->dependentfiles) {
1309                 for (i=0; *driver->dependentfiles[i]; i++) {
1310                         fstrcpy(temp_name, driver->dependentfiles[i]);
1311                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
1312                 }
1313         }
1314
1315         slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1316
1317         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1318
1319         buf = NULL;
1320         len = buflen = 0;
1321
1322  again:
1323         len = 0;
1324         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1325                         driver->cversion,
1326                         driver->name,
1327                         driver->environment,
1328                         driver->driverpath,
1329                         driver->datafile,
1330                         driver->configfile,
1331                         driver->helpfile,
1332                         driver->monitorname,
1333                         driver->defaultdatatype);
1334
1335         if (driver->dependentfiles) {
1336                 for (i=0; *driver->dependentfiles[i]; i++) {
1337                         len += tdb_pack(buf+len, buflen-len, "f",
1338                                         driver->dependentfiles[i]);
1339                 }
1340         }
1341
1342         if (len != buflen) {
1343                 buf = (char *)Realloc(buf, len);
1344                 buflen = len;
1345                 goto again;
1346         }
1347
1348
1349         kbuf.dptr = key;
1350         kbuf.dsize = strlen(key)+1;
1351         dbuf.dptr = buf;
1352         dbuf.dsize = len;
1353         
1354         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1355
1356         if (ret)
1357                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1358
1359         safe_free(buf);
1360         return ret;
1361 }
1362
1363 /****************************************************************************
1364 ****************************************************************************/
1365 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1366 {
1367         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1368
1369         ZERO_STRUCT(info3);
1370         info3.cversion = driver->version;
1371         fstrcpy(info3.name,driver->name);
1372         fstrcpy(info3.environment,driver->environment);
1373         fstrcpy(info3.driverpath,driver->driverpath);
1374         fstrcpy(info3.datafile,driver->datafile);
1375         fstrcpy(info3.configfile,driver->configfile);
1376         fstrcpy(info3.helpfile,driver->helpfile);
1377         fstrcpy(info3.monitorname,driver->monitorname);
1378         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1379         info3.dependentfiles = driver->dependentfiles;
1380
1381         return add_a_printer_driver_3(&info3);
1382 }
1383
1384
1385 /****************************************************************************
1386 ****************************************************************************/
1387 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1388 {
1389         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1390
1391         ZERO_STRUCT(info);
1392
1393         fstrcpy(info.name, in_prt);
1394         fstrcpy(info.defaultdatatype, "RAW");
1395         
1396         fstrcpy(info.driverpath, "");
1397         fstrcpy(info.datafile, "");
1398         fstrcpy(info.configfile, "");
1399         fstrcpy(info.helpfile, "");
1400
1401         if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1402                 return ERROR_NOT_ENOUGH_MEMORY;
1403
1404         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1405         fstrcpy(info.dependentfiles[0], "");
1406
1407         *info_ptr = memdup(&info, sizeof(info));
1408         
1409         return 0;       
1410 }
1411
1412 /****************************************************************************
1413 ****************************************************************************/
1414 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1415 {
1416         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1417         TDB_DATA kbuf, dbuf;
1418         fstring architecture;
1419         int len = 0;
1420         int i;
1421         pstring key;
1422
1423         ZERO_STRUCT(driver);
1424
1425         get_short_archi(architecture, in_arch);
1426
1427         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1428
1429         slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1430
1431         kbuf.dptr = key;
1432         kbuf.dsize = strlen(key)+1;
1433         
1434         dbuf = tdb_fetch(tdb, kbuf);
1435 #if 0
1436         if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1437 #else
1438         if (!dbuf.dptr) return 5;
1439 #endif
1440         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1441                           &driver.cversion,
1442                           driver.name,
1443                           driver.environment,
1444                           driver.driverpath,
1445                           driver.datafile,
1446                           driver.configfile,
1447                           driver.helpfile,
1448                           driver.monitorname,
1449                           driver.defaultdatatype);
1450
1451         i=0;
1452         while (len < dbuf.dsize) {
1453                 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1454                                                          sizeof(fstring)*(i+2));
1455                 if (driver.dependentfiles == NULL)
1456                         break;
1457
1458                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1459                                   &driver.dependentfiles[i]);
1460                 i++;
1461         }
1462         if (driver.dependentfiles != NULL)
1463                 fstrcpy(driver.dependentfiles[i], "");
1464
1465         safe_free(dbuf.dptr);
1466
1467         if (len != dbuf.dsize) {
1468                 if (driver.dependentfiles != NULL)
1469                         safe_free(driver.dependentfiles);
1470
1471                 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1472         }
1473
1474         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1475
1476         return 0;
1477 }
1478
1479 /****************************************************************************
1480 ****************************************************************************/
1481 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1482 {
1483         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1484         TDB_DATA kbuf;
1485         pstring key;
1486         int i;
1487         line[0] = '\0';
1488
1489         slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1490         DEBUG(10,("driver key: [%s]\n", key));
1491         
1492         kbuf.dptr = key;
1493         kbuf.dsize = strlen(key)+1;
1494         if (!tdb_exists(tdb, kbuf)) return False;
1495
1496         ZERO_STRUCT(info3);
1497         get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1498         
1499     DEBUGADD(10,("info3->name            [%s]\n", info3->name));
1500     DEBUGADD(10,("info3->datafile        [%s]\n", info3->datafile));
1501     DEBUGADD(10,("info3->helpfile        [%s]\n", info3->helpfile));
1502     DEBUGADD(10,("info3->monitorname     [%s]\n", info3->monitorname));
1503     DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1504         for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1505     DEBUGADD(10,("info3->dependentfiles  [%s]\n", info3->dependentfiles[i]));
1506     }
1507     DEBUGADD(10,("info3->environment     [%s]\n", info3->environment));
1508     DEBUGADD(10,("info3->driverpath      [%s]\n", info3->driverpath));
1509     DEBUGADD(10,("info3->configfile      [%s]\n", info3->configfile));
1510
1511         /*pstrcat(line, info3->name);             pstrcat(line, ":");*/
1512         trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1513         pstrcat(line, info3->configfile);
1514     pstrcat(line, ":");
1515         trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1516         pstrcat(line, info3->datafile);
1517     pstrcat(line, ":");
1518         trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1519         pstrcat(line, info3->helpfile);
1520     pstrcat(line, ":");
1521         trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1522         pstrcat(line, info3->monitorname);
1523     pstrcat(line, ":");
1524         pstrcat(line, "RAW");                /*info3->defaultdatatype);*/
1525     pstrcat(line, ":");
1526
1527         for (i=0; info3->dependentfiles &&
1528                  *info3->dependentfiles[i]; i++) {
1529                 if (i) pstrcat(line, ",");               /* don't end in a "," */
1530                 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1531                 pstrcat(line, info3->dependentfiles[i]);
1532         }
1533         
1534         free(info3);
1535
1536         return True;    
1537 }
1538
1539 /****************************************************************************
1540 debugging function, dump at level 6 the struct in the logs
1541 ****************************************************************************/
1542 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1543 {
1544         uint32 result;
1545         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1546         int i;
1547         
1548         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1549         
1550         switch (level)
1551         {
1552                 case 3:
1553                 {
1554                         if (driver.info_3 == NULL)
1555                                 result=5;
1556                         else {
1557                                 info3=driver.info_3;
1558                         
1559                                 DEBUGADD(106,("version:[%d]\n",         info3->cversion));
1560                                 DEBUGADD(106,("name:[%s]\n",            info3->name));
1561                                 DEBUGADD(106,("environment:[%s]\n",     info3->environment));
1562                                 DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
1563                                 DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
1564                                 DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
1565                                 DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
1566                                 DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
1567                                 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1568                                 
1569                                 for (i=0; info3->dependentfiles &&
1570                                           *info3->dependentfiles[i]; i++) {
1571                                         DEBUGADD(106,("dependentfile:[%s]\n",
1572                                                       info3->dependentfiles[i]));
1573                                 }
1574                                 result=0;
1575                         }
1576                         break;
1577                 }
1578                 default:
1579                         DEBUGADD(1,("Level not implemented\n"));
1580                         result=1;
1581                         break;
1582         }
1583         
1584         return result;
1585 }
1586
1587 /****************************************************************************
1588 ****************************************************************************/
1589 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1590 {
1591         int len = 0;
1592
1593         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1594
1595         if (!nt_devmode) return len;
1596
1597         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1598                         nt_devmode->devicename,
1599                         nt_devmode->formname,
1600
1601                         nt_devmode->specversion,
1602                         nt_devmode->driverversion,
1603                         nt_devmode->size,
1604                         nt_devmode->driverextra,
1605                         nt_devmode->orientation,
1606                         nt_devmode->papersize,
1607                         nt_devmode->paperlength,
1608                         nt_devmode->paperwidth,
1609                         nt_devmode->scale,
1610                         nt_devmode->copies,
1611                         nt_devmode->defaultsource,
1612                         nt_devmode->printquality,
1613                         nt_devmode->color,
1614                         nt_devmode->duplex,
1615                         nt_devmode->yresolution,
1616                         nt_devmode->ttoption,
1617                         nt_devmode->collate,
1618                         nt_devmode->logpixels,
1619                         
1620                         nt_devmode->fields,
1621                         nt_devmode->bitsperpel,
1622                         nt_devmode->pelswidth,
1623                         nt_devmode->pelsheight,
1624                         nt_devmode->displayflags,
1625                         nt_devmode->displayfrequency,
1626                         nt_devmode->icmmethod,
1627                         nt_devmode->icmintent,
1628                         nt_devmode->mediatype,
1629                         nt_devmode->dithertype,
1630                         nt_devmode->reserved1,
1631                         nt_devmode->reserved2,
1632                         nt_devmode->panningwidth,
1633                         nt_devmode->panningheight,
1634                         nt_devmode->private);
1635
1636         
1637         if (nt_devmode->private) {
1638                 len += tdb_pack(buf+len, buflen-len, "B",
1639                                 nt_devmode->driverextra,
1640                                 nt_devmode->private);
1641         }
1642
1643         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1644
1645         return len;
1646 }
1647
1648 /****************************************************************************
1649 ****************************************************************************/
1650 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1651 {
1652         int len = 0;
1653
1654         while (param != NULL) {
1655                 len += tdb_pack(buf+len, buflen-len, "pfdB",
1656                                 param,
1657                                 param->value,
1658                                 param->type,
1659                                 param->data_len,
1660                                 param->data);
1661                 param=param->next;      
1662         }
1663
1664         len += tdb_pack(buf+len, buflen-len, "p", param);
1665
1666         return len;
1667 }
1668
1669
1670 /****************************************************************************
1671 delete a printer - this just deletes the printer info file, any open
1672 handles are not affected
1673 ****************************************************************************/
1674 uint32 del_a_printer(char *sharename)
1675 {
1676         pstring key;
1677         TDB_DATA kbuf;
1678
1679         slprintf(key, sizeof(key), "%s%s",
1680                  PRINTERS_PREFIX, sharename);
1681
1682         kbuf.dptr=key;
1683         kbuf.dsize=strlen(key)+1;
1684
1685         tdb_delete(tdb, kbuf);
1686         return 0;
1687 }
1688
1689 /****************************************************************************
1690 ****************************************************************************/
1691 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1692 {
1693         pstring key;
1694         char *buf;
1695         int buflen, len, ret;
1696         TDB_DATA kbuf, dbuf;
1697         
1698         /*
1699          * in addprinter: no servername and the printer is the name
1700          * in setprinter: servername is \\server
1701          *                and printer is \\server\\printer
1702          *
1703          * Samba manages only local printers.
1704          * we currently don't support things like path=\\other_server\printer
1705          */
1706
1707         if (info->servername[0]!='\0') {
1708                 trim_string(info->printername, info->servername, NULL);
1709                 trim_string(info->printername, "\\", NULL);
1710                 info->servername[0]='\0';
1711         }
1712
1713         /*
1714          * JFM: one day I'll forget.
1715          * below that's info->portname because that's the SAMBA sharename
1716          * and I made NT 'thinks' it's the portname
1717          * the info->sharename is the thing you can name when you add a printer
1718          * that's the short-name when you create shared printer for 95/98
1719          * So I've made a limitation in SAMBA: you can only have 1 printer model
1720          * behind a SAMBA share.
1721          */
1722
1723         buf = NULL;
1724         buflen = 0;
1725
1726  again: 
1727         len = 0;
1728         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1729                         info->attributes,
1730                         info->priority,
1731                         info->default_priority,
1732                         info->starttime,
1733                         info->untiltime,
1734                         info->status,
1735                         info->cjobs,
1736                         info->averageppm,
1737                         info->changeid,
1738                         info->c_setprinter,
1739                         info->setuptime,
1740                         info->servername,
1741                         info->printername,
1742                         info->sharename,
1743                         info->portname,
1744                         info->drivername,
1745                         info->comment,
1746                         info->location,
1747                         info->sepfile,
1748                         info->printprocessor,
1749                         info->datatype,
1750                         info->parameters);
1751
1752         len += pack_devicemode(info->devmode, buf+len, buflen-len);
1753         len += pack_specifics(info->specific, buf+len, buflen-len);
1754
1755         if (buflen != len) {
1756                 buf = (char *)Realloc(buf, len);
1757                 buflen = len;
1758                 goto again;
1759         }
1760         
1761
1762         slprintf(key, sizeof(key), "%s%s",
1763                  PRINTERS_PREFIX, info->sharename);
1764
1765         kbuf.dptr = key;
1766         kbuf.dsize = strlen(key)+1;
1767         dbuf.dptr = buf;
1768         dbuf.dsize = len;
1769
1770         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1771
1772         if (ret == -1)
1773                 DEBUG(8, ("error updating printer to tdb on disk\n"));
1774
1775         safe_free(buf);
1776
1777         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1778                  info->sharename, info->drivername, info->portname, len));
1779
1780         return ret;
1781 }
1782
1783
1784 /****************************************************************************
1785 ****************************************************************************/
1786 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1787 {
1788         NT_PRINTER_PARAM *current;
1789         
1790         DEBUG(108,("add_a_specific_param\n"));  
1791
1792         (*param)->next=NULL;
1793         
1794         if (info_2->specific == NULL)
1795         {
1796                 info_2->specific=*param;
1797         }
1798         else
1799         {
1800                 current=info_2->specific;               
1801                 while (current->next != NULL) {
1802                         current=current->next;
1803                 }               
1804                 current->next=*param;
1805         }
1806
1807         *param = NULL;
1808 }
1809
1810 /****************************************************************************
1811 ****************************************************************************/
1812 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1813 {
1814         NT_PRINTER_PARAM *current;
1815         NT_PRINTER_PARAM *previous;
1816         
1817         current=info_2->specific;
1818         previous=current;
1819         
1820         if (current==NULL) return (False);
1821         
1822         if ( !strcmp(current->value, param->value) &&
1823             (strlen(current->value)==strlen(param->value)) ) {
1824                 DEBUG(109,("deleting first value\n"));
1825                 info_2->specific=current->next;
1826                 safe_free(current->data);
1827                 safe_free(current);
1828                 DEBUG(109,("deleted first value\n"));
1829                 return (True);
1830         }
1831
1832         current=previous->next;
1833                 
1834         while ( current!=NULL ) {
1835                 if (!strcmp(current->value, param->value) &&
1836                     strlen(current->value)==strlen(param->value) ) {
1837                         DEBUG(109,("deleting current value\n"));
1838                         previous->next=current->next;
1839                         safe_free(current->data);
1840                         safe_free(current);
1841                         DEBUG(109,("deleted current value\n"));
1842                         return(True);
1843                 }
1844                 
1845                 previous=previous->next;
1846                 current=current->next;
1847         }
1848         return (False);
1849 }
1850
1851 /****************************************************************************
1852  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
1853 ****************************************************************************/
1854 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
1855 {
1856         NT_PRINTER_PARAM *param = *param_ptr;
1857
1858         if(param == NULL)
1859                 return;
1860
1861         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
1862
1863         if(param->data)
1864                 safe_free(param->data);
1865
1866         safe_free(param);
1867         *param_ptr = NULL;
1868 }
1869
1870 /****************************************************************************
1871  Malloc and return an NT devicemode.
1872 ****************************************************************************/
1873
1874 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
1875 {
1876 /*
1877  * should I init this ones ???
1878         nt_devmode->devicename
1879 */
1880
1881         char adevice[32];
1882         NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
1883
1884         if (nt_devmode == NULL) {
1885                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
1886                 return NULL;
1887         }
1888
1889         ZERO_STRUCTP(nt_devmode);
1890
1891         safe_strcpy(adevice, default_devicename, sizeof(adevice));
1892         fstrcpy(nt_devmode->devicename, adevice);       
1893         
1894         fstrcpy(nt_devmode->formname, "Letter");
1895
1896         nt_devmode->specversion      = 0x0401;
1897         nt_devmode->driverversion    = 0x0400;
1898         nt_devmode->size             = 0x00DC;
1899         nt_devmode->driverextra      = 0x0000;
1900         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
1901                                        DEFAULTSOURCE | COPIES | SCALE |
1902                                        PAPERSIZE | ORIENTATION;
1903         nt_devmode->orientation      = 1;
1904         nt_devmode->papersize        = PAPER_LETTER;
1905         nt_devmode->paperlength      = 0;
1906         nt_devmode->paperwidth       = 0;
1907         nt_devmode->scale            = 0x64;
1908         nt_devmode->copies           = 01;
1909         nt_devmode->defaultsource    = BIN_FORMSOURCE;
1910         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
1911         nt_devmode->color            = COLOR_MONOCHROME;
1912         nt_devmode->duplex           = DUP_SIMPLEX;
1913         nt_devmode->yresolution      = 0;
1914         nt_devmode->ttoption         = TT_SUBDEV;
1915         nt_devmode->collate          = COLLATE_FALSE;
1916         nt_devmode->icmmethod        = 0;
1917         nt_devmode->icmintent        = 0;
1918         nt_devmode->mediatype        = 0;
1919         nt_devmode->dithertype       = 0;
1920
1921         /* non utilisés par un driver d'imprimante */
1922         nt_devmode->logpixels        = 0;
1923         nt_devmode->bitsperpel       = 0;
1924         nt_devmode->pelswidth        = 0;
1925         nt_devmode->pelsheight       = 0;
1926         nt_devmode->displayflags     = 0;
1927         nt_devmode->displayfrequency = 0;
1928         nt_devmode->reserved1        = 0;
1929         nt_devmode->reserved2        = 0;
1930         nt_devmode->panningwidth     = 0;
1931         nt_devmode->panningheight    = 0;
1932         
1933         nt_devmode->private=NULL;
1934
1935         return nt_devmode;
1936 }
1937
1938 /****************************************************************************
1939  Deepcopy an NT devicemode.
1940 ****************************************************************************/
1941
1942 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1943 {
1944         NT_DEVICEMODE *new_nt_devicemode = NULL;
1945
1946         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1947                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1948                 return NULL;
1949         }
1950
1951         new_nt_devicemode->private = NULL;
1952         if (nt_devicemode->private != NULL) {
1953                 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1954                         safe_free(new_nt_devicemode);
1955                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1956                         return NULL;
1957         }
1958         }
1959
1960         return new_nt_devicemode;
1961 }
1962
1963 /****************************************************************************
1964  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1965 ****************************************************************************/
1966
1967 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1968 {
1969         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1970
1971         if(nt_devmode == NULL)
1972                 return;
1973
1974         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
1975
1976         if(nt_devmode->private)
1977                 safe_free(nt_devmode->private);
1978
1979         safe_free(nt_devmode);
1980         *devmode_ptr = NULL;
1981 }
1982
1983 /****************************************************************************
1984  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
1985 ****************************************************************************/
1986 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
1987 {
1988         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
1989         NT_PRINTER_PARAM *param_ptr;
1990
1991         if(info == NULL)
1992                 return;
1993
1994         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
1995
1996         free_nt_devicemode(&info->devmode);
1997         free_sec_desc_buf(&info->secdesc_buf);
1998
1999         for(param_ptr = info->specific; param_ptr; ) {
2000                 NT_PRINTER_PARAM *tofree = param_ptr;
2001
2002                 param_ptr = param_ptr->next;
2003                 free_nt_printer_param(&tofree);
2004         }
2005
2006         safe_free(*info_ptr);
2007         *info_ptr = NULL;
2008 }
2009
2010
2011 /****************************************************************************
2012 ****************************************************************************/
2013 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2014 {
2015         int len = 0;
2016         int extra_len = 0;
2017         NT_DEVICEMODE devmode;
2018
2019         ZERO_STRUCT(devmode);
2020
2021         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2022
2023         if (!*nt_devmode) return len;
2024
2025         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2026                           devmode.devicename,
2027                           devmode.formname,
2028
2029                           &devmode.specversion,
2030                           &devmode.driverversion,
2031                           &devmode.size,
2032                           &devmode.driverextra,
2033                           &devmode.orientation,
2034                           &devmode.papersize,
2035                           &devmode.paperlength,
2036                           &devmode.paperwidth,
2037                           &devmode.scale,
2038                           &devmode.copies,
2039                           &devmode.defaultsource,
2040                           &devmode.printquality,
2041                           &devmode.color,
2042                           &devmode.duplex,
2043                           &devmode.yresolution,
2044                           &devmode.ttoption,
2045                           &devmode.collate,
2046                           &devmode.logpixels,
2047                         
2048                           &devmode.fields,
2049                           &devmode.bitsperpel,
2050                           &devmode.pelswidth,
2051                           &devmode.pelsheight,
2052                           &devmode.displayflags,
2053                           &devmode.displayfrequency,
2054                           &devmode.icmmethod,
2055                           &devmode.icmintent,
2056                           &devmode.mediatype,
2057                           &devmode.dithertype,
2058                           &devmode.reserved1,
2059                           &devmode.reserved2,
2060                           &devmode.panningwidth,
2061                           &devmode.panningheight,
2062                           &devmode.private);
2063         
2064         if (devmode.private) {
2065                 /* the len in tdb_unpack is an int value and
2066                  * devmoce.driverextra is only a short
2067                  */
2068                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2069                 devmode.driverextra=(uint16)extra_len;
2070         }
2071
2072         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2073
2074         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2075         if (devmode.private)
2076                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2077
2078         return len;
2079 }
2080
2081 /****************************************************************************
2082 ****************************************************************************/
2083 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2084 {
2085         int len = 0;
2086         NT_PRINTER_PARAM param, *p;
2087
2088         *list = NULL;
2089
2090         while (1) {
2091                 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2092                 if (!p) break;
2093
2094                 len += tdb_unpack(buf+len, buflen-len, "fdB",
2095                                   param.value,
2096                                   &param.type,
2097                                   &param.data_len,
2098                                   &param.data);
2099                 param.next = *list;
2100                 *list = memdup(&param, sizeof(param));
2101
2102                 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2103         }
2104
2105         return len;
2106 }
2107
2108
2109 /****************************************************************************
2110 get a default printer info 2 struct
2111 ****************************************************************************/
2112 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2113 {
2114         extern pstring global_myname;
2115         int snum;
2116         NT_PRINTER_INFO_LEVEL_2 info;
2117
2118         ZERO_STRUCT(info);
2119
2120         snum = lp_servicenumber(sharename);
2121
2122         slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2123         slprintf(info.printername, sizeof(info.printername), "\\\\%s\\%s", 
2124                  global_myname, sharename);
2125         fstrcpy(info.sharename, sharename);
2126         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2127         fstrcpy(info.drivername, lp_printerdriver(snum));
2128
2129         if (!*info.drivername)
2130                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2131
2132         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2133
2134         pstrcpy(info.comment, "");
2135         fstrcpy(info.printprocessor, "winprint");
2136         fstrcpy(info.datatype, "RAW");
2137
2138         info.attributes = PRINTER_ATTRIBUTE_SHARED   \
2139                          | PRINTER_ATTRIBUTE_LOCAL  \
2140                          | PRINTER_ATTRIBUTE_RAW_ONLY \
2141                          | PRINTER_ATTRIBUTE_QUEUED ;            /* attributes */
2142
2143         info.starttime = 0; /* Minutes since 12:00am GMT */
2144         info.untiltime = 0; /* Minutes since 12:00am GMT */
2145         info.priority = 1;
2146         info.default_priority = 1;
2147         info.setuptime = (uint32)time(NULL);
2148
2149         if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2150                 goto fail;
2151
2152         if (!nt_printing_getsec(sharename, &info.secdesc_buf))
2153                 goto fail;
2154
2155         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2156         if (! *info_ptr) {
2157                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2158                 goto fail;
2159         }
2160
2161         return (0);     
2162
2163   fail:
2164
2165         if (info.devmode)
2166                 free_nt_devicemode(&info.devmode);
2167         if (info.secdesc_buf)
2168                 free_sec_desc_buf(&info.secdesc_buf);
2169         return 2;
2170 }
2171
2172 /****************************************************************************
2173 ****************************************************************************/
2174 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2175 {
2176         pstring key;
2177         NT_PRINTER_INFO_LEVEL_2 info;
2178         int len = 0;
2179         TDB_DATA kbuf, dbuf;
2180         fstring printername;
2181                 
2182         ZERO_STRUCT(info);
2183
2184         slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
2185
2186         kbuf.dptr = key;
2187         kbuf.dsize = strlen(key)+1;
2188
2189         dbuf = tdb_fetch(tdb, kbuf);
2190         if (!dbuf.dptr)
2191                 return get_a_printer_2_default(info_ptr, sharename);
2192
2193         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2194                         &info.attributes,
2195                         &info.priority,
2196                         &info.default_priority,
2197                         &info.starttime,
2198                         &info.untiltime,
2199                         &info.status,
2200                         &info.cjobs,
2201                         &info.averageppm,
2202                         &info.changeid,
2203                         &info.c_setprinter,
2204                         &info.setuptime,
2205                         info.servername,
2206                         info.printername,
2207                         info.sharename,
2208                         info.portname,
2209                         info.drivername,
2210                         info.comment,
2211                         info.location,
2212                         info.sepfile,
2213                         info.printprocessor,
2214                         info.datatype,
2215                         info.parameters);
2216
2217         /* Samba has to have shared raw drivers. */
2218         info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2219
2220         /* Restore the stripped strings. */
2221         slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2222         slprintf(printername, sizeof(printername), "\\\\%s\\%s", global_myname,
2223                         info.printername);
2224         fstrcpy(info.printername, printername);
2225
2226         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2227         len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2228
2229         nt_printing_getsec(sharename, &info.secdesc_buf);
2230
2231         safe_free(dbuf.dptr);
2232         *info_ptr=memdup(&info, sizeof(info));
2233
2234         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2235                  sharename, info.printername, info.drivername));
2236
2237         
2238         return 0;       
2239 }
2240
2241 /****************************************************************************
2242 debugging function, dump at level 6 the struct in the logs
2243 ****************************************************************************/
2244 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2245 {
2246         uint32 result;
2247         NT_PRINTER_INFO_LEVEL_2 *info2;
2248         
2249         DEBUG(106,("Dumping printer at level [%d]\n", level));
2250         
2251         switch (level)
2252         {
2253                 case 2:
2254                 {
2255                         if (printer.info_2 == NULL)
2256                                 result=5;
2257                         else
2258                         {
2259                                 info2=printer.info_2;
2260                         
2261                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2262                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2263                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2264                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2265                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2266                                 DEBUGADD(106,("status:[%d]\n", info2->status));
2267                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2268                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2269                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2270                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2271                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2272
2273                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2274                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2275                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2276                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2277                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2278                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2279                                 DEBUGADD(106,("location:[%s]\n", info2->location));
2280                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2281                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2282                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2283                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2284                                 result=0;
2285                         }
2286                         break;
2287                 }
2288                 default:
2289                         DEBUGADD(1,("Level not implemented\n"));
2290                         result=1;
2291                         break;
2292         }
2293         
2294         return result;
2295 }
2296
2297 /****************************************************************************
2298  Get the parameters we can substitute in an NT print job.
2299 ****************************************************************************/
2300
2301 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2302 {
2303         NT_PRINTER_INFO_LEVEL *printer = NULL;
2304
2305         **printername = **sharename = **portname = '\0';
2306
2307         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2308                 return;
2309
2310         fstrcpy(*printername, printer->info_2->printername);
2311         fstrcpy(*sharename, printer->info_2->sharename);
2312         fstrcpy(*portname, printer->info_2->portname);
2313
2314         free_a_printer(&printer, 2);
2315 }
2316
2317 /*
2318  * The function below are the high level ones.
2319  * only those ones must be called from the spoolss code.
2320  * JFM.
2321  */
2322
2323 /****************************************************************************
2324  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2325 ****************************************************************************/
2326
2327 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2328 {
2329         uint32 result;
2330         
2331         dump_a_printer(printer, level); 
2332         
2333         switch (level)
2334         {
2335                 case 2:
2336                 {
2337                         printer.info_2->c_setprinter++;
2338                         result=update_a_printer_2(printer.info_2);
2339                         break;
2340                 }
2341                 default:
2342                         result=1;
2343                         break;
2344         }
2345         
2346         return result;
2347 }
2348
2349 /****************************************************************************
2350  Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2351  We split this out from mod_a_printer as it updates the id's and timestamps.
2352 ****************************************************************************/
2353
2354 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2355 {
2356         uint32 result;
2357         
2358         dump_a_printer(printer, level); 
2359         
2360         switch (level)
2361         {
2362                 case 2:
2363                 {
2364                         /*
2365                          * Update the changestamp.
2366                          * Note we must *not* do this in mod_a_printer().
2367                          */
2368                         NTTIME time_nt;
2369                         time_t time_unix = time(NULL);
2370                         unix_to_nt_time(&time_nt, time_unix);
2371                         printer.info_2->changeid=time_nt.low;
2372
2373                         printer.info_2->c_setprinter++;
2374                         result=update_a_printer_2(printer.info_2);
2375                         break;
2376                 }
2377                 default:
2378                         result=1;
2379                         break;
2380         }
2381         
2382         return result;
2383 }
2384
2385 /****************************************************************************
2386  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2387 ****************************************************************************/
2388
2389 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2390 {
2391         uint32 result;
2392         NT_PRINTER_INFO_LEVEL *printer = NULL;
2393         
2394         *pp_printer = NULL;
2395
2396         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2397
2398         switch (level)
2399         {
2400                 case 2:
2401                 {
2402                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2403                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
2404                                 return 1;
2405                         }
2406                         ZERO_STRUCTP(printer);
2407                         result=get_a_printer_2(&printer->info_2, sharename);
2408                         if (result == 0) {
2409                                 dump_a_printer(*printer, level);
2410                                 *pp_printer = printer;
2411                         } else {
2412                                 safe_free(printer);
2413                         }
2414                         break;
2415                 }
2416                 default:
2417                         result=1;
2418                         break;
2419         }
2420         
2421         DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2422
2423         return result;
2424 }
2425
2426 /****************************************************************************
2427  Deletes a NT_PRINTER_INFO_LEVEL struct.
2428 ****************************************************************************/
2429
2430 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2431 {
2432         uint32 result;
2433         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2434
2435         DEBUG(104,("freeing a printer at level [%d]\n", level));
2436
2437         if (printer == NULL)
2438                 return 0;
2439         
2440         switch (level)
2441         {
2442                 case 2:
2443                 {
2444                         if (printer->info_2 != NULL)
2445                         {
2446                                 free_nt_printer_info_level_2(&printer->info_2);
2447                                 result=0;
2448                         }
2449                         else
2450                         {
2451                                 result=4;
2452                         }
2453                         break;
2454                 }
2455                 default:
2456                         result=1;
2457                         break;
2458         }
2459
2460         safe_free(printer);
2461         *pp_printer = NULL;
2462         return result;
2463 }
2464
2465 /****************************************************************************
2466 ****************************************************************************/
2467 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2468 {
2469         uint32 result;
2470         DEBUG(104,("adding a printer at level [%d]\n", level));
2471         dump_a_printer_driver(driver, level);
2472         
2473         switch (level)
2474         {
2475                 case 3:
2476                 {
2477                         result=add_a_printer_driver_3(driver.info_3);
2478                         break;
2479                 }
2480
2481                 case 6:
2482                 {
2483                         result=add_a_printer_driver_6(driver.info_6);
2484                         break;
2485                 }
2486                 default:
2487                         result=1;
2488                         break;
2489         }
2490         
2491         return result;
2492 }
2493 /****************************************************************************
2494 ****************************************************************************/
2495 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2496                             fstring printername, fstring architecture, uint32 version)
2497 {
2498         uint32 result;
2499         
2500         switch (level)
2501         {
2502                 case 3:
2503                 {
2504                         result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2505                         break;
2506                 }
2507                 default:
2508                         result=1;
2509                         break;
2510         }
2511         
2512         if (result == 0)
2513                 dump_a_printer_driver(*driver, level);
2514         return result;
2515 }
2516
2517 /****************************************************************************
2518 ****************************************************************************/
2519 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2520 {
2521         uint32 result;
2522         
2523         switch (level)
2524         {
2525                 case 3:
2526                 {
2527                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2528                         if (driver.info_3 != NULL)
2529                         {
2530                                 info3=driver.info_3;
2531                                 safe_free(info3->dependentfiles);
2532                                 ZERO_STRUCTP(info3);
2533                                 safe_free(info3);
2534                                 result=0;
2535                         }
2536                         else
2537                         {
2538                                 result=4;
2539                         }
2540                         break;
2541                 }
2542                 case 6:
2543                 {
2544                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2545                         if (driver.info_6 != NULL)
2546                         {
2547                                 info6=driver.info_6;
2548                                 safe_free(info6->dependentfiles);
2549                                 safe_free(info6->previousnames);
2550                                 ZERO_STRUCTP(info6);
2551                                 safe_free(info6);
2552                                 result=0;
2553                         }
2554                         else
2555                         {
2556                                 result=4;
2557                         }
2558                         break;
2559                 }
2560                 default:
2561                         result=1;
2562                         break;
2563         }
2564         return result;
2565 }
2566
2567 /****************************************************************************
2568 ****************************************************************************/
2569 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2570                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
2571 {
2572         /* right now that's enough ! */ 
2573         NT_PRINTER_PARAM *param;
2574         int i=0;
2575         
2576         param=printer.info_2->specific;
2577         
2578         while (param != NULL && i < param_index) {
2579                 param=param->next;
2580                 i++;
2581         }
2582         
2583         if (param == NULL)
2584                 return False;
2585
2586         /* exited because it exist */
2587         *type=param->type;              
2588         StrnCpy(value, param->value, sizeof(fstring)-1);
2589         *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2590         if(*data == NULL)
2591                 return False;
2592         ZERO_STRUCTP(*data);
2593         memcpy(*data, param->data, param->data_len);
2594         *len=param->data_len;
2595         return True;
2596 }
2597
2598 /****************************************************************************
2599 ****************************************************************************/
2600 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2601                         fstring value, uint8 **data, uint32 *type, uint32 *len)
2602 {
2603         /* right now that's enough ! */ 
2604         NT_PRINTER_PARAM *param;
2605         
2606         DEBUG(105, ("get_specific_param\n"));
2607         
2608         param=printer.info_2->specific;
2609                 
2610         while (param != NULL)
2611         {
2612 #if 1 /* JRA - I think this should be case insensitive.... */
2613                 if ( strequal(value, param->value)
2614 #else
2615                 if ( !strcmp(value, param->value)
2616 #endif
2617                     && strlen(value)==strlen(param->value))
2618                         break;
2619                         
2620                 param=param->next;
2621         }
2622         
2623         DEBUG(106, ("found one param\n"));
2624         if (param != NULL)
2625         {
2626                 /* exited because it exist */
2627                 *type=param->type;      
2628                 
2629                 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2630                 if(*data == NULL)
2631                         return False;
2632                 memcpy(*data, param->data, param->data_len);
2633                 *len=param->data_len;
2634
2635                 DEBUG(106, ("exit of get_specific_param:true\n"));
2636                 return (True);
2637         }
2638         DEBUG(106, ("exit of get_specific_param:false\n"));
2639         return (False);
2640 }
2641
2642 /****************************************************************************
2643  Store a security desc for a printer.
2644 ****************************************************************************/
2645
2646 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2647 {
2648         SEC_DESC_BUF *new_secdesc_ctr = NULL;
2649         SEC_DESC_BUF *old_secdesc_ctr = NULL;
2650         prs_struct ps;
2651         TALLOC_CTX *mem_ctx = NULL;
2652         fstring key;
2653         uint32 status;
2654
2655         mem_ctx = talloc_init();
2656         if (mem_ctx == NULL)
2657                 return False;
2658
2659         /* The old owner and group sids of the security descriptor are not
2660            present when new ACEs are added or removed by changing printer
2661            permissions through NT.  If they are NULL in the new security
2662            descriptor then copy them over from the old one. */
2663
2664         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
2665                 DOM_SID *owner_sid, *group_sid;
2666                 SEC_ACL *dacl, *sacl;
2667                 SEC_DESC *psd = NULL;
2668                 size_t size;
2669
2670                 nt_printing_getsec(printername, &old_secdesc_ctr);
2671
2672                 /* Pick out correct owner and group sids */
2673
2674                 owner_sid = secdesc_ctr->sec->owner_sid ?
2675                         secdesc_ctr->sec->owner_sid :
2676                         old_secdesc_ctr->sec->owner_sid;
2677
2678                 group_sid = secdesc_ctr->sec->grp_sid ?
2679                         secdesc_ctr->sec->grp_sid :
2680                         old_secdesc_ctr->sec->grp_sid;
2681
2682                 dacl = secdesc_ctr->sec->dacl ?
2683                         secdesc_ctr->sec->dacl :
2684                         old_secdesc_ctr->sec->dacl;
2685
2686                 sacl = secdesc_ctr->sec->sacl ?
2687                         secdesc_ctr->sec->sacl :
2688                         old_secdesc_ctr->sec->sacl;
2689
2690                 /* Make a deep copy of the security descriptor */
2691
2692                 psd = make_sec_desc(secdesc_ctr->sec->revision,
2693                                     owner_sid, group_sid,
2694                                     sacl,
2695                                     dacl,
2696                                     &size);
2697
2698                 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2699
2700                 /* Free up memory */
2701
2702                 free_sec_desc(&psd);
2703                 free_sec_desc_buf(&old_secdesc_ctr);
2704         }
2705
2706         if (!new_secdesc_ctr) {
2707                 new_secdesc_ctr = secdesc_ctr;
2708         }
2709
2710         /* Store the security descriptor in a tdb */
2711
2712         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
2713                  sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
2714
2715         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
2716                              &ps, 1)) {
2717                 status = ERROR_INVALID_FUNCTION;
2718                 goto out;
2719         }
2720
2721         slprintf(key, sizeof(key), "SECDESC/%s", printername);
2722
2723         if (tdb_prs_store(tdb, key, &ps)==0) {
2724                 status = 0;
2725         } else {
2726                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2727                 status = ERROR_INVALID_FUNCTION;
2728         }
2729
2730         /* Free mallocated memory */
2731
2732  out:
2733         free_sec_desc_buf(&old_secdesc_ctr);
2734
2735         if (new_secdesc_ctr != secdesc_ctr) {
2736                 free_sec_desc_buf(&new_secdesc_ctr);
2737         }
2738
2739         prs_mem_free(&ps);
2740         if (mem_ctx)
2741                 talloc_destroy(mem_ctx);
2742         return status;
2743 }
2744
2745 /****************************************************************************
2746  Construct a default security descriptor buffer for a printer.
2747 ****************************************************************************/
2748
2749 static SEC_DESC_BUF *construct_default_printer_sdb(void)
2750 {
2751         SEC_ACE ace[2];
2752         SEC_ACCESS sa;
2753         SEC_ACL *psa = NULL;
2754         SEC_DESC_BUF *sdb = NULL;
2755         SEC_DESC *psd = NULL;
2756         DOM_SID owner_sid;
2757         size_t sd_size;
2758         enum SID_NAME_USE name_type;
2759
2760         /* Create an ACE where Everyone is allowed to print */
2761
2762         init_sec_access(&sa, PRINTER_ACE_PRINT);
2763         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2764                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2765
2766
2767         /* Make the security descriptor owned by the Administrators group
2768            on the PDC of the domain. */
2769
2770         if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
2771                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2772         } else {
2773
2774                 /* Backup plan - make printer owned by admins or root.  This should
2775                    emulate a lanman printer as security settings can't be
2776                    changed. */
2777
2778                 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
2779                         !lookup_name( "Administrators", &owner_sid, &name_type) &&
2780                         !lookup_name( "Administrator", &owner_sid, &name_type) &&
2781                         !lookup_name("root", &owner_sid, &name_type)) {
2782                                                 sid_copy(&owner_sid, &global_sid_World);
2783                 }
2784         }
2785
2786         init_sec_access(&sa, PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT);
2787         init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2788                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2789
2790         /* The ACL revision number in rpc_secdesc.h differs from the one
2791            created by NT when setting ACE entries in printer
2792            descriptors.  NT4 complains about the property being edited by a
2793            NT5 machine. */
2794
2795 #define NT4_ACL_REVISION 0x2
2796
2797         if ((psa = make_sec_acl(NT4_ACL_REVISION, 2, ace)) != NULL) {
2798                 psd = make_sec_desc(SEC_DESC_REVISION,
2799                                     &owner_sid, NULL,
2800                                     NULL, psa, &sd_size);
2801                 free_sec_acl(&psa);
2802         }
2803
2804         if (!psd) {
2805                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2806                 return NULL;
2807         }
2808
2809         sdb = make_sec_desc_buf(sd_size, psd);
2810
2811         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2812                  (unsigned int)sd_size));
2813
2814         free_sec_desc(&psd);
2815         return sdb;
2816 }
2817
2818 /****************************************************************************
2819  Get a security desc for a printer.
2820 ****************************************************************************/
2821
2822 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
2823 {
2824         prs_struct ps;
2825         TALLOC_CTX *mem_ctx = NULL;
2826         fstring key;
2827
2828         mem_ctx = talloc_init();
2829         if (mem_ctx == NULL)
2830                 return False;
2831
2832         /* Fetch security descriptor from tdb */
2833
2834         slprintf(key, sizeof(key), "SECDESC/%s", printername);
2835
2836         if (tdb_prs_fetch(tdb, key, &ps, mem_ctx)!=0 ||
2837             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
2838
2839                 DEBUG(4,("using default secdesc for %s\n", printername));
2840
2841                 if (!(*secdesc_ctr = construct_default_printer_sdb())) {
2842                         talloc_destroy(mem_ctx);
2843                         return False;
2844                 }
2845
2846                 talloc_destroy(mem_ctx);
2847                 return True;
2848         }
2849
2850         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2851            this security descriptor has been created when winbindd was
2852            down.  Take ownership of security descriptor. */
2853
2854         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
2855                 DOM_SID owner_sid;
2856                 enum SID_NAME_USE name_type;
2857
2858                 /* Change sd owner to workgroup administrator */
2859
2860                 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
2861                                         &name_type)) {
2862                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
2863                         SEC_DESC *psd = NULL;
2864                         size_t size;
2865
2866                         /* Create new sd */
2867
2868                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2869
2870                         psd = make_sec_desc((*secdesc_ctr)->sec->revision,
2871                                             &owner_sid,
2872                                             (*secdesc_ctr)->sec->grp_sid,
2873                                             (*secdesc_ctr)->sec->sacl,
2874                                             (*secdesc_ctr)->sec->dacl,
2875                                             &size);
2876
2877                         new_secdesc_ctr = make_sec_desc_buf(size, psd);
2878
2879                         free_sec_desc(&psd);
2880
2881                         /* Swap with other one */
2882
2883                         free_sec_desc_buf(secdesc_ctr);
2884                         *secdesc_ctr = new_secdesc_ctr;
2885
2886                         /* Set it */
2887
2888                         nt_printing_setsec(printername, *secdesc_ctr);
2889                 }
2890         }
2891
2892         prs_mem_free(&ps);
2893         talloc_destroy(mem_ctx);
2894         return True;
2895 }
2896
2897 /* error code:
2898         0: everything OK
2899         1: level not implemented
2900         2: file doesn't exist
2901         3: can't allocate memory
2902         4: can't free memory
2903         5: non existant struct
2904 */
2905
2906 /*
2907         A printer and a printer driver are 2 different things.
2908         NT manages them separatelly, Samba does the same.
2909         Why ? Simply because it's easier and it makes sense !
2910         
2911         Now explanation: You have 3 printers behind your samba server,
2912         2 of them are the same make and model (laser A and B). But laser B
2913         has an 3000 sheet feeder and laser A doesn't such an option.
2914         Your third printer is an old dot-matrix model for the accounting :-).
2915         
2916         If the /usr/local/samba/lib directory (default dir), you will have
2917         5 files to describe all of this.
2918         
2919         3 files for the printers (1 by printer):
2920                 NTprinter_laser A
2921                 NTprinter_laser B
2922                 NTprinter_accounting
2923         2 files for the drivers (1 for the laser and 1 for the dot matrix)
2924                 NTdriver_printer model X
2925                 NTdriver_printer model Y
2926
2927 jfm: I should use this comment for the text file to explain
2928         same thing for the forms BTW.
2929         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2930
2931 */
2932
2933 /****************************************************************************
2934  Check a user has permissions to perform the given operation.  We use some
2935  constants defined in include/rpc_spoolss.h that look relevant to check
2936  the various actions we perform when checking printer access.
2937
2938    PRINTER_ACCESS_ADMINISTER:
2939        print_queue_pause, print_queue_resume, update_printer_sec,
2940        update_printer, spoolss_addprinterex_level_2,
2941        _spoolss_setprinterdata
2942
2943    PRINTER_ACCESS_USE:
2944        print_job_start
2945
2946    JOB_ACCESS_ADMINISTER:
2947        print_job_delete, print_job_pause, print_job_resume,
2948        print_queue_purge
2949
2950  ****************************************************************************/
2951 BOOL print_access_check(struct current_user *user, int snum, int access_type)
2952 {
2953         SEC_DESC_BUF *secdesc = NULL;
2954         uint32 access_granted, status, required_access = 0;
2955         BOOL result;
2956         char *pname;
2957         int i;
2958         extern struct current_user current_user;
2959         
2960         /* If user is NULL then use the current_user structure */
2961
2962         if (!user) user = &current_user;
2963
2964         /* Always allow root or printer admins to do anything */
2965
2966         if (user->uid == 0 ||
2967             user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
2968                 return True;
2969         }
2970
2971         /* Get printer name */
2972
2973         pname = PRINTERNAME(snum);
2974
2975         if (!pname || !*pname)
2976                 pname = SERVICE(snum);
2977
2978         if (!pname || !*pname) {
2979                 errno = EACCES;
2980                 return False;
2981         }
2982
2983         /* Get printer security descriptor */
2984
2985         nt_printing_getsec(pname, &secdesc);
2986
2987         /* Check against NT4 ACE mask values.  From observation these
2988            values are:
2989
2990                Access Type       ACE Mask    Constant
2991                -------------------------------------
2992                Full Control      0x10000000  PRINTER_ACE_FULL_CONTROL
2993                Print             0xe0000000  PRINTER_ACE_PRINT
2994                Manage Documents  0x00020000  PRINTER_ACE_MANAGE_DOCUMENTS
2995         */
2996
2997         switch (access_type) {
2998         case PRINTER_ACCESS_USE:
2999                 required_access = PRINTER_ACE_PRINT;
3000                 break;
3001         case PRINTER_ACCESS_ADMINISTER:
3002                 required_access = PRINTER_ACE_MANAGE_DOCUMENTS |
3003                         PRINTER_ACE_PRINT;
3004                 break;
3005         case JOB_ACCESS_ADMINISTER:
3006                 required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
3007                 break;
3008         default:
3009                 DEBUG(0, ("invalid value passed to print_access_check()\n"));
3010                 result = False;
3011                 goto done;
3012         }       
3013
3014         /* The ACE for Full Control in a printer security descriptor
3015            doesn't seem to map properly to the access checking model.  For
3016            it to work properly it should be the logical OR of all the other
3017            values, i.e PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT.
3018            This would cause the access check to simply fall out when we
3019            check against any subset of these bits.  To get things to work,
3020            change every ACE mask of PRINTER_ACE_FULL_CONTROL to
3021            PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before
3022            performing the access check.  I'm sure there is a better way to
3023            do this! */
3024
3025         if (secdesc && secdesc->sec && secdesc->sec->dacl &&
3026             secdesc->sec->dacl->ace) {
3027                 for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
3028                         if (secdesc->sec->dacl->ace[i].info.mask ==
3029                             PRINTER_ACE_FULL_CONTROL) {
3030                                 secdesc->sec->dacl->ace[i].info.mask =
3031                                         PRINTER_ACE_MANAGE_DOCUMENTS |
3032                                         PRINTER_ACE_PRINT;
3033                         }
3034                 }
3035         }
3036
3037         if ((result = se_access_check(secdesc->sec, user, required_access,
3038                                       &access_granted, &status))) {
3039                 goto done;
3040         }
3041
3042         /* Check against NT5 ACE mask values.  From observation these
3043            values are:
3044
3045                Access Type       ACE Mask    Constant
3046                -------------------------------------
3047                Full Control      0x000f000c  PRINTER_ACE_NT5_FULL_CONTROL
3048                Print             0x00020008  PRINTER_ACE_NT5_PRINT
3049                Manage Documents  0x00020000  PRINTER_ACE_NT5_MANAGE_DOCUMENTS
3050
3051            NT5 likes to rewrite the security descriptor and change the ACE
3052            masks from NT4 format to NT5 format making them unreadable by
3053            NT4 clients. */
3054
3055         switch (access_type) {
3056         case PRINTER_ACCESS_USE:
3057                 required_access = PRINTER_ACE_NT5_PRINT;
3058                 break;
3059         case PRINTER_ACCESS_ADMINISTER:
3060                 required_access = PRINTER_ACE_NT5_FULL_CONTROL;
3061                 break;
3062         case JOB_ACCESS_ADMINISTER:
3063                 required_access = PRINTER_ACE_NT5_MANAGE_DOCUMENTS;
3064                 break;
3065         }       
3066
3067         result = se_access_check(secdesc->sec, user, required_access,
3068                                  &access_granted, &status);
3069
3070         /* Check access */
3071         
3072  done:
3073         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3074         
3075         /* Free mallocated memory */
3076
3077         free_sec_desc_buf(&secdesc);
3078
3079         if (!result)
3080                 errno = EACCES;
3081
3082         return result;
3083 }
3084
3085 /****************************************************************************
3086  Check the time parameters allow a print operation.
3087 *****************************************************************************/
3088
3089 BOOL print_time_access_check(int snum)
3090 {
3091         NT_PRINTER_INFO_LEVEL *printer = NULL;
3092         BOOL ok = False;
3093         time_t now = time(NULL);
3094         struct tm *t;
3095         uint32 mins;
3096
3097         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3098                 return False;
3099
3100         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3101                 ok = True;
3102
3103         t = gmtime(&now);
3104         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3105
3106         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3107                 ok = True;
3108
3109         free_a_printer(&printer, 2);
3110
3111         if (!ok)
3112                 errno = EACCES;
3113
3114         return ok;
3115 }
3116
3117
3118 #undef OLD_NTDOMAIN