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