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