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