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