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