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