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