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