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