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