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