fix bug 294; win9x driver lookups should always use version 0
[gd/samba/.git] / source / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2003.
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 DOM_SID global_sid_World;
26
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37  
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41  
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
43
44 /* Map generic permissions to printer object specific permissions */
45
46 GENERIC_MAPPING printer_generic_mapping = {
47         PRINTER_READ,
48         PRINTER_WRITE,
49         PRINTER_EXECUTE,
50         PRINTER_ALL_ACCESS
51 };
52
53 STANDARD_MAPPING printer_std_mapping = {
54         PRINTER_READ,
55         PRINTER_WRITE,
56         PRINTER_EXECUTE,
57         PRINTER_ALL_ACCESS
58 };
59
60 /* Map generic permissions to print server object specific permissions */
61
62 GENERIC_MAPPING printserver_generic_mapping = {
63         SERVER_READ,
64         SERVER_WRITE,
65         SERVER_EXECUTE,
66         SERVER_ALL_ACCESS
67 };
68
69 STANDARD_MAPPING printserver_std_mapping = {
70         SERVER_READ,
71         SERVER_WRITE,
72         SERVER_EXECUTE,
73         SERVER_ALL_ACCESS
74 };
75
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms[] = {
81         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
199 };
200
201 struct table_node {
202         const char      *long_archi;
203         const char      *short_archi;
204         int     version;
205 };
206  
207 #define SPL_ARCH_WIN40          "WIN40"
208 #define SPL_ARCH_W32X86         "W32X86"
209 #define SPL_ARCH_W32MIPS        "W32MIPS"
210 #define SPL_ARCH_W32ALPHA       "W32ALPHA"
211 #define SPL_ARCH_W32PPC         "W32PPC"
212
213 static const struct table_node archi_table[]= {
214
215         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
216         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
217         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
218         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
219         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
220         {NULL,                   "",            -1 }
221 };
222
223 static BOOL upgrade_to_version_3(void)
224 {
225         TDB_DATA kbuf, newkey, dbuf;
226  
227         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
228  
229         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
230                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
231
232                 dbuf = tdb_fetch(tdb_drivers, kbuf);
233
234                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
235                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
236                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
237                                 SAFE_FREE(dbuf.dptr);
238                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
239                                 return False;
240                         }
241                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
242                                 SAFE_FREE(dbuf.dptr);
243                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
244                                 return False;
245                         }
246                 }
247  
248                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
249                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
251                                 SAFE_FREE(dbuf.dptr);
252                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
253                                 return False;
254                         }
255                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
256                                 SAFE_FREE(dbuf.dptr);
257                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
258                                 return False;
259                         }
260                 }
261  
262                 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
263                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
265                                 SAFE_FREE(dbuf.dptr);
266                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
267                                 return False;
268                         }
269                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
270                                 SAFE_FREE(dbuf.dptr);
271                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
272                                 return False;
273                         }
274                 }
275  
276                 SAFE_FREE(dbuf.dptr);
277         }
278
279         return True;
280 }
281
282 /****************************************************************************
283  Open the NT printing tdbs. Done once before fork().
284 ****************************************************************************/
285
286 BOOL nt_printing_init(void)
287 {
288         static pid_t local_pid;
289         const char *vstring = "INFO/version";
290
291         if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
292                 return True;
293  
294         if (tdb_drivers)
295                 tdb_close(tdb_drivers);
296         tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
297         if (!tdb_drivers) {
298                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299                         lock_path("ntdrivers.tdb"), strerror(errno) ));
300                 return False;
301         }
302  
303         if (tdb_printers)
304                 tdb_close(tdb_printers);
305         tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
306         if (!tdb_printers) {
307                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308                         lock_path("ntprinters.tdb"), strerror(errno) ));
309                 return False;
310         }
311  
312         if (tdb_forms)
313                 tdb_close(tdb_forms);
314         tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
315         if (!tdb_forms) {
316                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317                         lock_path("ntforms.tdb"), strerror(errno) ));
318                 return False;
319         }
320  
321         local_pid = sys_getpid();
322  
323         /* handle a Samba upgrade */
324         tdb_lock_bystring(tdb_drivers, vstring, 0);
325         {
326                 int32 vers_id;
327
328                 /* Cope with byte-reversed older versions of the db. */
329                 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
330                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
331                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
332                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
333                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
334                         vers_id = NTDRIVERS_DATABASE_VERSION;
335                 }
336
337                 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
338
339                         if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { 
340                                 if (!upgrade_to_version_3())
341                                         return False;
342                         } else
343                                 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
344                          
345                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
346                 }
347         }
348         tdb_unlock_bystring(tdb_drivers, vstring);
349
350         update_c_setprinter(True);
351
352         /*
353          * register callback to handle updating printers as new
354          * drivers are installed
355          */
356
357         message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
358
359         /*
360          * register callback to handle updating printer data
361          * when a driver is initialized
362          */
363
364         message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
365
366
367         return True;
368 }
369
370 /*******************************************************************
371  tdb traversal function for counting printers.
372 ********************************************************************/
373
374 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
375                                       TDB_DATA data, void *context)
376 {
377         int *printer_count = (int*)context;
378  
379         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
380                 (*printer_count)++;
381                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
382         }
383  
384         return 0;
385 }
386  
387 /*******************************************************************
388  Update the spooler global c_setprinter. This variable is initialized
389  when the parent smbd starts with the number of existing printers. It
390  is monotonically increased by the current number of printers *after*
391  each add or delete printer RPC. Only Microsoft knows why... JRR020119
392 ********************************************************************/
393
394 uint32 update_c_setprinter(BOOL initialize)
395 {
396         int32 c_setprinter;
397         int32 printer_count = 0;
398  
399         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
400  
401         /* Traverse the tdb, counting the printers */
402         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
403  
404         /* If initializing, set c_setprinter to current printers count
405          * otherwise, bump it by the current printer count
406          */
407         if (!initialize)
408                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
409         else
410                 c_setprinter = printer_count;
411  
412         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
413         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
414  
415         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
416  
417         return (uint32)c_setprinter;
418 }
419
420 /*******************************************************************
421  Get the spooler global c_setprinter, accounting for initialization.
422 ********************************************************************/
423
424 uint32 get_c_setprinter(void)
425 {
426         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
427  
428         if (c_setprinter == (int32)-1)
429                 c_setprinter = update_c_setprinter(True);
430  
431         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
432  
433         return (uint32)c_setprinter;
434 }
435
436 /****************************************************************************
437  Get builtin form struct list.
438 ****************************************************************************/
439
440 int get_builtin_ntforms(nt_forms_struct **list)
441 {
442         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
443         return sizeof(default_forms) / sizeof(default_forms[0]);
444 }
445
446 /****************************************************************************
447  get a builtin form struct
448 ****************************************************************************/
449
450 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
451 {
452         int i,count;
453         fstring form_name;
454         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
455         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
456         count = sizeof(default_forms) / sizeof(default_forms[0]);
457         for (i=0;i<count;i++) {
458                 if (strequal(form_name,default_forms[i].name)) {
459                         DEBUGADD(6,("Found builtin form %s \n", form_name));
460                         memcpy(form,&default_forms[i],sizeof(*form));
461                         break;
462                 }
463         }
464
465         return (i !=count);
466 }
467
468 /****************************************************************************
469 get a form struct list
470 ****************************************************************************/
471 int get_ntforms(nt_forms_struct **list)
472 {
473         TDB_DATA kbuf, newkey, dbuf;
474         nt_forms_struct *tl;
475         nt_forms_struct form;
476         int ret;
477         int i;
478         int n = 0;
479
480         for (kbuf = tdb_firstkey(tdb_forms);
481              kbuf.dptr;
482              newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
483         {
484                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) 
485                         continue;
486                 
487                 dbuf = tdb_fetch(tdb_forms, kbuf);
488                 if (!dbuf.dptr) 
489                         continue;
490
491                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
492                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
493                                  &i, &form.flag, &form.width, &form.length, &form.left,
494                                  &form.top, &form.right, &form.bottom);
495                 SAFE_FREE(dbuf.dptr);
496                 if (ret != dbuf.dsize) 
497                         continue;
498
499                 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
500                 if (!tl) {
501                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
502                         return 0;
503                 }
504                 *list = tl;
505                 (*list)[n] = form;
506                 n++;
507         }
508         
509
510         return n;
511 }
512
513 /****************************************************************************
514 write a form struct list
515 ****************************************************************************/
516 int write_ntforms(nt_forms_struct **list, int number)
517 {
518         pstring buf, key;
519         int len;
520         TDB_DATA kbuf,dbuf;
521         int i;
522
523         for (i=0;i<number;i++) {
524                 /* save index, so list is rebuilt in correct order */
525                 len = tdb_pack(buf, sizeof(buf), "dddddddd",
526                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
527                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
528                                (*list)[i].bottom);
529                 if (len > sizeof(buf)) break;
530                 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
531                 kbuf.dsize = strlen(key)+1;
532                 kbuf.dptr = key;
533                 dbuf.dsize = len;
534                 dbuf.dptr = buf;
535                 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
536        }
537
538        return i;
539 }
540
541 /****************************************************************************
542 add a form struct at the end of the list
543 ****************************************************************************/
544 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
545 {
546         int n=0;
547         BOOL update;
548         fstring form_name;
549         nt_forms_struct *tl;
550
551         /*
552          * NT tries to add forms even when
553          * they are already in the base
554          * only update the values if already present
555          */
556
557         update=False;
558         
559         unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
560         for (n=0; n<*count; n++) {
561                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
562                         DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
563                         update=True;
564                         break;
565                 }
566         }
567
568         if (update==False) {
569                 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
570                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
571                         return False;
572                 }
573                 *list = tl;
574                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
575                 (*count)++;
576         }
577         
578         (*list)[n].flag=form->flags;
579         (*list)[n].width=form->size_x;
580         (*list)[n].length=form->size_y;
581         (*list)[n].left=form->left;
582         (*list)[n].top=form->top;
583         (*list)[n].right=form->right;
584         (*list)[n].bottom=form->bottom;
585
586         return True;
587 }
588
589 /****************************************************************************
590  Delete a named form struct.
591 ****************************************************************************/
592
593 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
594 {
595         pstring key;
596         TDB_DATA kbuf;
597         int n=0;
598         fstring form_name;
599
600         *ret = WERR_OK;
601
602         unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
603
604         for (n=0; n<*count; n++) {
605                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
606                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
607                         break;
608                 }
609         }
610
611         if (n == *count) {
612                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
613                 *ret = WERR_INVALID_PARAM;
614                 return False;
615         }
616
617         slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
618         kbuf.dsize = strlen(key)+1;
619         kbuf.dptr = key;
620         if (tdb_delete(tdb_forms, kbuf) != 0) {
621                 *ret = WERR_NOMEM;
622                 return False;
623         }
624
625         return True;
626 }
627
628 /****************************************************************************
629  Update a form struct.
630 ****************************************************************************/
631
632 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
633 {
634         int n=0;
635         fstring form_name;
636         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
637
638         DEBUG(106, ("[%s]\n", form_name));
639         for (n=0; n<count; n++) {
640                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
641                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
642                         break;
643         }
644
645         if (n==count) return;
646
647         (*list)[n].flag=form->flags;
648         (*list)[n].width=form->size_x;
649         (*list)[n].length=form->size_y;
650         (*list)[n].left=form->left;
651         (*list)[n].top=form->top;
652         (*list)[n].right=form->right;
653         (*list)[n].bottom=form->bottom;
654 }
655
656 /****************************************************************************
657  Get the nt drivers list.
658  Traverse the database and look-up the matching names.
659 ****************************************************************************/
660 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
661 {
662         int total=0;
663         const char *short_archi;
664         fstring *fl;
665         pstring key;
666         TDB_DATA kbuf, newkey;
667
668         short_archi = get_short_archi(architecture);
669         slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
670
671         for (kbuf = tdb_firstkey(tdb_drivers);
672              kbuf.dptr;
673              newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
674
675                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
676                         continue;
677                 
678                 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
679                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
680                         return -1;
681                 }
682                 else *list = fl;
683
684                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
685                 total++;
686         }
687
688         return(total);
689 }
690
691 /****************************************************************************
692 function to do the mapping between the long architecture name and
693 the short one.
694 ****************************************************************************/
695 const char *get_short_archi(const char *long_archi)
696 {
697         int i=-1;
698
699         DEBUG(107,("Getting architecture dependant directory\n"));
700         do {
701                 i++;
702         } while ( (archi_table[i].long_archi!=NULL ) &&
703                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
704
705         if (archi_table[i].long_archi==NULL) {
706                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
707                 return NULL;
708         }
709
710         /* this might be client code - but shouldn't this be an fstrcpy etc? */
711
712
713         DEBUGADD(108,("index: [%d]\n", i));
714         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
715         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
716
717         return archi_table[i].short_archi;
718 }
719
720 /****************************************************************************
721  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
722  There are two case to be covered here: PE (Portable Executable) and NE (New
723  Executable) files. Both files support the same INFO structure, but PE files
724  store the signature in unicode, and NE files store it as !unicode.
725  returns -1 on error, 1 on version info found, and 0 on no version info found.
726 ****************************************************************************/
727
728 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
729 {
730         int     i;
731         char    *buf;
732         ssize_t byte_count;
733
734         if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
735                 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736                                 fname, PE_HEADER_SIZE));
737                 goto error_exit;
738         }
739
740         /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
742                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
743                                 fname, byte_count));
744                 goto no_version_info;
745         }
746
747         /* Is this really a DOS header? */
748         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
749                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
751                 goto no_version_info;
752         }
753
754         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
755         if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
756                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
757                                 fname, errno));
758                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759                 goto no_version_info;
760         }
761
762         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
763                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
764                                 fname, byte_count));
765                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766                 goto no_version_info;
767         }
768
769         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
770         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
771                 int num_sections;
772                 int section_table_bytes;
773                 
774                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
775                         DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776                                         fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
777                         /* At this point, we assume the file is in error. It still could be somthing
778                          * else besides a PE file, but it unlikely at this point.
779                          */
780                         goto error_exit;
781                 }
782
783                 /* get the section table */
784                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
785                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
786                 SAFE_FREE(buf);
787                 if ((buf=malloc(section_table_bytes)) == NULL) {
788                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
789                                         fname, section_table_bytes));
790                         goto error_exit;
791                 }
792
793                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
794                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
795                                         fname, byte_count));
796                         goto error_exit;
797                 }
798
799                 /* Iterate the section table looking for the resource section ".rsrc" */
800                 for (i = 0; i < num_sections; i++) {
801                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
802
803                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
804                                 int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
805                                 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
806
807                                 SAFE_FREE(buf);
808                                 if ((buf=malloc(section_bytes)) == NULL) {
809                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
810                                                         fname, section_bytes));
811                                         goto error_exit;
812                                 }
813
814                                 /* Seek to the start of the .rsrc section info */
815                                 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
816                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
817                                                         fname, errno));
818                                         goto error_exit;
819                                 }
820
821                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
822                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
823                                                         fname, byte_count));
824                                         goto error_exit;
825                                 }
826
827                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
828                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
829                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
830                                                 /* Align to next long address */
831                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
832
833                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
834                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
835                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
836                                                         
837                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
838                                                                           fname, *major, *minor,
839                                                                           (*major>>16)&0xffff, *major&0xffff,
840                                                                           (*minor>>16)&0xffff, *minor&0xffff));
841                                                         SAFE_FREE(buf);
842                                                         return 1;
843                                                 }
844                                         }
845                                 }
846                         }
847                 }
848
849                 /* Version info not found, fall back to origin date/time */
850                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
851                 SAFE_FREE(buf);
852                 return 0;
853
854         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
855                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
856                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
857                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
858                         /* At this point, we assume the file is in error. It still could be somthing
859                          * else besides a NE file, but it unlikely at this point. */
860                         goto error_exit;
861                 }
862
863                 /* Allocate a bit more space to speed up things */
864                 SAFE_FREE(buf);
865                 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
866                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
867                                         fname, PE_HEADER_SIZE));
868                         goto error_exit;
869                 }
870
871                 /* This is a HACK! I got tired of trying to sort through the messy
872                  * 'NE' file format. If anyone wants to clean this up please have at
873                  * it, but this works. 'NE' files will eventually fade away. JRR */
874                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
875                         /* Cover case that should not occur in a well formed 'NE' .dll file */
876                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
877
878                         for(i=0; i<byte_count; i++) {
879                                 /* Fast skip past data that can't possibly match */
880                                 if (buf[i] != 'V') continue;
881
882                                 /* Potential match data crosses buf boundry, move it to beginning
883                                  * of buf, and fill the buf with as much as it will hold. */
884                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
885                                         int bc;
886
887                                         memcpy(buf, &buf[i], byte_count-i);
888                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
889                                                                    (byte_count-i))) < 0) {
890
891                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
892                                                                  fname, errno));
893                                                 goto error_exit;
894                                         }
895
896                                         byte_count = bc + (byte_count - i);
897                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
898
899                                         i = 0;
900                                 }
901
902                                 /* Check that the full signature string and the magic number that
903                                  * follows exist (not a perfect solution, but the chances that this
904                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
905                                  * twice, as it is simpler to read the code. */
906                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
907                                         /* Compute skip alignment to next long address */
908                                         int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
909                                                                  sizeof(VS_SIGNATURE)) & 3;
910                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
911
912                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
913                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
914                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
915                                                           fname, *major, *minor,
916                                                           (*major>>16)&0xffff, *major&0xffff,
917                                                           (*minor>>16)&0xffff, *minor&0xffff));
918                                         SAFE_FREE(buf);
919                                         return 1;
920                                 }
921                         }
922                 }
923
924                 /* Version info not found, fall back to origin date/time */
925                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
926                 SAFE_FREE(buf);
927                 return 0;
928
929         } else
930                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
931                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
932                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
933
934         no_version_info:
935                 SAFE_FREE(buf);
936                 return 0;
937
938         error_exit:
939                 SAFE_FREE(buf);
940                 return -1;
941 }
942
943 /****************************************************************************
944 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
945 share one or more files. During the MS installation process files are checked
946 to insure that only a newer version of a shared file is installed over an
947 older version. There are several possibilities for this comparison. If there
948 is no previous version, the new one is newer (obviously). If either file is
949 missing the version info structure, compare the creation date (on Unix use
950 the modification date). Otherwise chose the numerically larger version number.
951 ****************************************************************************/
952
953 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
954 {
955         BOOL   use_version = True;
956         pstring filepath;
957
958         uint32 new_major;
959         uint32 new_minor;
960         time_t new_create_time;
961
962         uint32 old_major;
963         uint32 old_minor;
964         time_t old_create_time;
965
966         int access_mode;
967         int action;
968         files_struct    *fsp = NULL;
969         SMB_STRUCT_STAT st;
970         SMB_STRUCT_STAT stat_buf;
971         BOOL bad_path;
972
973         ZERO_STRUCT(st);
974         ZERO_STRUCT(stat_buf);
975         new_create_time = (time_t)0;
976         old_create_time = (time_t)0;
977
978         /* Get file version info (if available) for previous file (if it exists) */
979         pstrcpy(filepath, old_file);
980
981         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
982
983         fsp = open_file_shared(conn, filepath, &stat_buf,
984                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
985                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
986                                                    0, 0, &access_mode, &action);
987         if (!fsp) {
988                 /* Old file not found, so by definition new file is in fact newer */
989                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
990                                 filepath, errno));
991                 return True;
992
993         } else {
994                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
995                 if (ret == -1) goto error_exit;
996
997                 if (!ret) {
998                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
999                                          old_file));
1000                         use_version = False;
1001                         if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1002                         old_create_time = st.st_mtime;
1003                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1004                 }
1005         }
1006         close_file(fsp, True);
1007
1008         /* Get file version info (if available) for new file */
1009         pstrcpy(filepath, new_file);
1010         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1011
1012         fsp = open_file_shared(conn, filepath, &stat_buf,
1013                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
1014                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1015                                                    0, 0, &access_mode, &action);
1016         if (!fsp) {
1017                 /* New file not found, this shouldn't occur if the caller did its job */
1018                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1019                                 filepath, errno));
1020                 goto error_exit;
1021
1022         } else {
1023                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1024                 if (ret == -1) goto error_exit;
1025
1026                 if (!ret) {
1027                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1028                                          new_file));
1029                         use_version = False;
1030                         if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1031                         new_create_time = st.st_mtime;
1032                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1033                 }
1034         }
1035         close_file(fsp, True);
1036
1037         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1038                 /* Compare versions and choose the larger version number */
1039                 if (new_major > old_major ||
1040                         (new_major == old_major && new_minor > old_minor)) {
1041                         
1042                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1043                         return True;
1044                 }
1045                 else {
1046                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1047                         return False;
1048                 }
1049
1050         } else {
1051                 /* Compare modification time/dates and choose the newest time/date */
1052                 if (new_create_time > old_create_time) {
1053                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1054                         return True;
1055                 }
1056                 else {
1057                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1058                         return False;
1059                 }
1060         }
1061
1062         error_exit:
1063                 if(fsp)
1064                         close_file(fsp, True);
1065                 return -1;
1066 }
1067
1068 /****************************************************************************
1069 Determine the correct cVersion associated with an architecture and driver
1070 ****************************************************************************/
1071 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1072                                    struct current_user *user, WERROR *perr)
1073 {
1074         int               cversion;
1075         int               access_mode;
1076         int               action;
1077         NTSTATUS          nt_status;
1078         pstring           driverpath;
1079         DATA_BLOB         null_pw;
1080         fstring           res_type;
1081         files_struct      *fsp = NULL;
1082         BOOL              bad_path;
1083         SMB_STRUCT_STAT   st;
1084         connection_struct *conn;
1085
1086         ZERO_STRUCT(st);
1087
1088         *perr = WERR_INVALID_PARAM;
1089
1090         /* If architecture is Windows 95/98/ME, the version is always 0. */
1091         if (strcmp(architecture, "WIN40") == 0) {
1092                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1093                 *perr = WERR_OK;
1094                 return 0;
1095         }
1096
1097         /*
1098          * Connect to the print$ share under the same account as the user connected
1099          * to the rpc pipe. Note we must still be root to do this.
1100          */
1101
1102         /* Null password is ok - we are already an authenticated user... */
1103         null_pw = data_blob(NULL, 0);
1104         fstrcpy(res_type, "A:");
1105         become_root();
1106         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1107         unbecome_root();
1108
1109         if (conn == NULL) {
1110                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1111                 *perr = ntstatus_to_werror(nt_status);
1112                 return -1;
1113         }
1114
1115         /* We are temporarily becoming the connection user. */
1116         if (!become_user(conn, user->vuid)) {
1117                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1118                 *perr = WERR_ACCESS_DENIED;
1119                 return -1;
1120         }
1121
1122         /* Open the driver file (Portable Executable format) and determine the
1123          * deriver the cversion. */
1124         slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1125
1126         unix_convert(driverpath,conn,NULL,&bad_path,&st);
1127
1128         fsp = open_file_shared(conn, driverpath, &st,
1129                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
1130                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1131                                                    0, 0, &access_mode, &action);
1132         if (!fsp) {
1133                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1134                                 driverpath, errno));
1135                 *perr = WERR_ACCESS_DENIED;
1136                 goto error_exit;
1137         }
1138         else {
1139                 uint32 major;
1140                 uint32 minor;
1141                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1142                 if (ret == -1) goto error_exit;
1143
1144                 if (!ret) {
1145                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1146                         goto error_exit;
1147                 }
1148
1149                 /*
1150                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1151                  * for more details. Version in this case is not just the version of the 
1152                  * file, but the version in the sense of kernal mode (2) vs. user mode
1153                  * (3) drivers. Other bits of the version fields are the version info. 
1154                  * JRR 010716
1155                 */
1156                 cversion = major & 0x0000ffff;
1157                 switch (cversion) {
1158                         case 2: /* WinNT drivers */
1159                         case 3: /* Win2K drivers */
1160                                 break;
1161                         
1162                         default:
1163                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1164                                         driverpath, cversion));
1165                                 goto error_exit;
1166                 }
1167
1168                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1169                                   driverpath, major, minor));
1170         }
1171
1172     DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1173                         driverpath, cversion));
1174
1175         close_file(fsp, True);
1176         close_cnum(conn, user->vuid);
1177         unbecome_user();
1178         *perr = WERR_OK;
1179         return cversion;
1180
1181
1182   error_exit:
1183
1184         if(fsp)
1185                 close_file(fsp, True);
1186
1187         close_cnum(conn, user->vuid);
1188         unbecome_user();
1189         return -1;
1190 }
1191
1192 /****************************************************************************
1193 ****************************************************************************/
1194 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1195                                                                                          struct current_user *user)
1196 {
1197         const char *architecture;
1198         fstring new_name;
1199         char *p;
1200         int i;
1201         WERROR err;
1202
1203         /* clean up the driver name.
1204          * we can get .\driver.dll
1205          * or worse c:\windows\system\driver.dll !
1206          */
1207         /* using an intermediate string to not have overlaping memcpy()'s */
1208         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1209                 fstrcpy(new_name, p+1);
1210                 fstrcpy(driver->driverpath, new_name);
1211         }
1212
1213         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1214                 fstrcpy(new_name, p+1);
1215                 fstrcpy(driver->datafile, new_name);
1216         }
1217
1218         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1219                 fstrcpy(new_name, p+1);
1220                 fstrcpy(driver->configfile, new_name);
1221         }
1222
1223         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1224                 fstrcpy(new_name, p+1);
1225                 fstrcpy(driver->helpfile, new_name);
1226         }
1227
1228         if (driver->dependentfiles) {
1229                 for (i=0; *driver->dependentfiles[i]; i++) {
1230                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1231                                 fstrcpy(new_name, p+1);
1232                                 fstrcpy(driver->dependentfiles[i], new_name);
1233                         }
1234                 }
1235         }
1236
1237         architecture = get_short_archi(driver->environment);
1238         
1239         /* jfm:7/16/2000 the client always sends the cversion=0.
1240          * The server should check which version the driver is by reading
1241          * the PE header of driver->driverpath.
1242          *
1243          * For Windows 95/98 the version is 0 (so the value sent is correct)
1244          * For Windows NT (the architecture doesn't matter)
1245          *      NT 3.1: cversion=0
1246          *      NT 3.5/3.51: cversion=1
1247          *      NT 4: cversion=2
1248          *      NT2K: cversion=3
1249          */
1250         if ((driver->cversion = get_correct_cversion( architecture,
1251                                                                         driver->driverpath, user, &err)) == -1)
1252                 return err;
1253
1254         return WERR_OK;
1255 }
1256         
1257 /****************************************************************************
1258 ****************************************************************************/
1259 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1260 {
1261         const char *architecture;
1262         fstring new_name;
1263         char *p;
1264         int i;
1265         WERROR err;
1266
1267         /* clean up the driver name.
1268          * we can get .\driver.dll
1269          * or worse c:\windows\system\driver.dll !
1270          */
1271         /* using an intermediate string to not have overlaping memcpy()'s */
1272         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1273                 fstrcpy(new_name, p+1);
1274                 fstrcpy(driver->driverpath, new_name);
1275         }
1276
1277         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1278                 fstrcpy(new_name, p+1);
1279                 fstrcpy(driver->datafile, new_name);
1280         }
1281
1282         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1283                 fstrcpy(new_name, p+1);
1284                 fstrcpy(driver->configfile, new_name);
1285         }
1286
1287         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1288                 fstrcpy(new_name, p+1);
1289                 fstrcpy(driver->helpfile, new_name);
1290         }
1291
1292         if (driver->dependentfiles) {
1293                 for (i=0; *driver->dependentfiles[i]; i++) {
1294                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1295                                 fstrcpy(new_name, p+1);
1296                                 fstrcpy(driver->dependentfiles[i], new_name);
1297                         }
1298                 }
1299         }
1300
1301         architecture = get_short_archi(driver->environment);
1302
1303         /* jfm:7/16/2000 the client always sends the cversion=0.
1304          * The server should check which version the driver is by reading
1305          * the PE header of driver->driverpath.
1306          *
1307          * For Windows 95/98 the version is 0 (so the value sent is correct)
1308          * For Windows NT (the architecture doesn't matter)
1309          *      NT 3.1: cversion=0
1310          *      NT 3.5/3.51: cversion=1
1311          *      NT 4: cversion=2
1312          *      NT2K: cversion=3
1313          */
1314         if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1315                 return err;
1316
1317         return WERR_OK;
1318 }
1319
1320 /****************************************************************************
1321 ****************************************************************************/
1322 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1323                                                           uint32 level, struct current_user *user)
1324 {
1325         switch (level) {
1326                 case 3:
1327                 {
1328                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1329                         driver=driver_abstract.info_3;
1330                         return clean_up_driver_struct_level_3(driver, user);
1331                 }
1332                 case 6:
1333                 {
1334                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1335                         driver=driver_abstract.info_6;
1336                         return clean_up_driver_struct_level_6(driver, user);
1337                 }
1338                 default:
1339                         return WERR_INVALID_PARAM;
1340         }
1341 }
1342
1343 /****************************************************************************
1344  This function sucks and should be replaced. JRA.
1345 ****************************************************************************/
1346
1347 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1348 {
1349     dst->cversion  = src->version;
1350
1351     fstrcpy( dst->name, src->name);
1352     fstrcpy( dst->environment, src->environment);
1353     fstrcpy( dst->driverpath, src->driverpath);
1354     fstrcpy( dst->datafile, src->datafile);
1355     fstrcpy( dst->configfile, src->configfile);
1356     fstrcpy( dst->helpfile, src->helpfile);
1357     fstrcpy( dst->monitorname, src->monitorname);
1358     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1359     dst->dependentfiles = src->dependentfiles;
1360 }
1361
1362 #if 0 /* Debugging function */
1363
1364 static char* ffmt(unsigned char *c){
1365         int i;
1366         static char ffmt_str[17];
1367
1368         for (i=0; i<16; i++) {
1369                 if ((c[i] < ' ') || (c[i] > '~'))
1370                         ffmt_str[i]='.';
1371                 else
1372                         ffmt_str[i]=c[i];
1373         }
1374     ffmt_str[16]='\0';
1375         return ffmt_str;
1376 }
1377
1378 #endif
1379
1380 /****************************************************************************
1381 ****************************************************************************/
1382 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1383                                   struct current_user *user, WERROR *perr)
1384 {
1385         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1386         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1387         const char *architecture;
1388         pstring new_dir;
1389         pstring old_name;
1390         pstring new_name;
1391         DATA_BLOB null_pw;
1392         connection_struct *conn;
1393         NTSTATUS nt_status;
1394         pstring inbuf;
1395         pstring outbuf;
1396         fstring res_type;
1397         int ver = 0;
1398         int i;
1399
1400         memset(inbuf, '\0', sizeof(inbuf));
1401         memset(outbuf, '\0', sizeof(outbuf));
1402         *perr = WERR_OK;
1403
1404         if (level==3)
1405                 driver=driver_abstract.info_3;
1406         else if (level==6) {
1407                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1408                 driver = &converted_driver;
1409         } else {
1410                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1411                 return False;
1412         }
1413
1414         architecture = get_short_archi(driver->environment);
1415
1416         /*
1417          * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1418          * Note we must be root to do this.
1419          */
1420
1421         null_pw = data_blob(NULL, 0);
1422         fstrcpy(res_type, "A:");
1423         become_root();
1424         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1425         unbecome_root();
1426
1427         if (conn == NULL) {
1428                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1429                 *perr = ntstatus_to_werror(nt_status);
1430                 return False;
1431         }
1432
1433         /*
1434          * Save who we are - we are temporarily becoming the connection user.
1435          */
1436
1437         if (!become_user(conn, conn->vuid)) {
1438                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1439                 return False;
1440         }
1441
1442         /*
1443          * make the directories version and version\driver_name
1444          * under the architecture directory.
1445          */
1446         DEBUG(5,("Creating first directory\n"));
1447         slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1448         mkdir_internal(conn, new_dir);
1449
1450         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1451          * listed for this driver which has already been moved, skip it (note:
1452          * drivers may list the same file name several times. Then check if the
1453          * file already exists in archi\cversion\, if so, check that the version
1454          * info (or time stamps if version info is unavailable) is newer (or the
1455          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1456          * Otherwise, delete the file.
1457          *
1458          * If a file is not moved to archi\cversion\ because of an error, all the
1459          * rest of the 'unmoved' driver files are removed from archi\. If one or
1460          * more of the driver's files was already moved to archi\cversion\, it
1461          * potentially leaves the driver in a partially updated state. Version
1462          * trauma will most likely occur if an client attempts to use any printer
1463          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1464          * done is appropriate... later JRR
1465          */
1466
1467         DEBUG(5,("Moving files now !\n"));
1468
1469         if (driver->driverpath && strlen(driver->driverpath)) {
1470                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);      
1471                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
1472                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1473                         NTSTATUS status;
1474                         status = rename_internals(conn, new_name, old_name, True);
1475                         if (!NT_STATUS_IS_OK(status)) {
1476                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1477                                                 new_name, old_name));
1478                                 *perr = ntstatus_to_werror(status);
1479                                 unlink_internals(conn, 0, new_name);
1480                                 ver = -1;
1481                         }
1482                 }
1483                 else
1484                         unlink_internals(conn, 0, new_name);
1485         }
1486
1487         if (driver->datafile && strlen(driver->datafile)) {
1488                 if (!strequal(driver->datafile, driver->driverpath)) {
1489                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);        
1490                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
1491                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1492                                 NTSTATUS status;
1493                                 status = rename_internals(conn, new_name, old_name, True);
1494                                 if (!NT_STATUS_IS_OK(status)) {
1495                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1496                                                         new_name, old_name));
1497                                         *perr = ntstatus_to_werror(status);
1498                                         unlink_internals(conn, 0, new_name);
1499                                         ver = -1;
1500                                 }
1501                         }
1502                         else
1503                                 unlink_internals(conn, 0, new_name);
1504                 }
1505         }
1506
1507         if (driver->configfile && strlen(driver->configfile)) {
1508                 if (!strequal(driver->configfile, driver->driverpath) &&
1509                         !strequal(driver->configfile, driver->datafile)) {
1510                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);      
1511                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
1512                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1513                                 NTSTATUS status;
1514                                 status = rename_internals(conn, new_name, old_name, True);
1515                                 if (!NT_STATUS_IS_OK(status)) {
1516                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1517                                                         new_name, old_name));
1518                                         *perr = ntstatus_to_werror(status);
1519                                         unlink_internals(conn, 0, new_name);
1520                                         ver = -1;
1521                                 }
1522                         }
1523                         else
1524                                 unlink_internals(conn, 0, new_name);
1525                 }
1526         }
1527
1528         if (driver->helpfile && strlen(driver->helpfile)) {
1529                 if (!strequal(driver->helpfile, driver->driverpath) &&
1530                         !strequal(driver->helpfile, driver->datafile) &&
1531                         !strequal(driver->helpfile, driver->configfile)) {
1532                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);        
1533                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
1534                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1535                                 NTSTATUS status;
1536                                 status = rename_internals(conn, new_name, old_name, True);
1537                                 if (!NT_STATUS_IS_OK(status)) {
1538                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1539                                                         new_name, old_name));
1540                                         *perr = ntstatus_to_werror(status);
1541                                         unlink_internals(conn, 0, new_name);
1542                                         ver = -1;
1543                                 }
1544                         }
1545                         else
1546                                 unlink_internals(conn, 0, new_name);
1547                 }
1548         }
1549
1550         if (driver->dependentfiles) {
1551                 for (i=0; *driver->dependentfiles[i]; i++) {
1552                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1553                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1554                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1555                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1556                                 int j;
1557                                 for (j=0; j < i; j++) {
1558                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1559                                                 goto NextDriver;
1560                                         }
1561                                 }
1562
1563                                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);       
1564                                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
1565                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1566                                         NTSTATUS status;
1567                                         status = rename_internals(conn, new_name, old_name, True);
1568                                         if (!NT_STATUS_IS_OK(status)) {
1569                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1570                                                                 new_name, old_name));
1571                                                 *perr = ntstatus_to_werror(status);
1572                                                 unlink_internals(conn, 0, new_name);
1573                                                 ver = -1;
1574                                         }
1575                                 }
1576                                 else
1577                                         unlink_internals(conn, 0, new_name);
1578                         }
1579                 NextDriver: ;
1580                 }
1581         }
1582
1583         close_cnum(conn, user->vuid);
1584         unbecome_user();
1585
1586         return ver == -1 ? False : True;
1587 }
1588
1589 /****************************************************************************
1590 ****************************************************************************/
1591 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1592 {
1593         int len, buflen;
1594         const char *architecture;
1595         pstring directory;
1596         fstring temp_name;
1597         pstring key;
1598         char *buf;
1599         int i, ret;
1600         TDB_DATA kbuf, dbuf;
1601
1602         architecture = get_short_archi(driver->environment);
1603
1604         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1605          * \\server is added in the rpc server layer.
1606          * It does make sense to NOT store the server's name in the printer TDB.
1607          */
1608
1609         slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1610
1611         /* .inf files do not always list a file for each of the four standard files. 
1612          * Don't prepend a path to a null filename, or client claims:
1613          *   "The server on which the printer resides does not have a suitable 
1614          *   <printer driver name> printer driver installed. Click OK if you 
1615          *   wish to install the driver on your local machine."
1616          */
1617         if (strlen(driver->driverpath)) {
1618                 fstrcpy(temp_name, driver->driverpath);
1619                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1620         }
1621
1622         if (strlen(driver->datafile)) {
1623                 fstrcpy(temp_name, driver->datafile);
1624                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1625         }
1626
1627         if (strlen(driver->configfile)) {
1628                 fstrcpy(temp_name, driver->configfile);
1629                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1630         }
1631
1632         if (strlen(driver->helpfile)) {
1633                 fstrcpy(temp_name, driver->helpfile);
1634                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1635         }
1636
1637         if (driver->dependentfiles) {
1638                 for (i=0; *driver->dependentfiles[i]; i++) {
1639                         fstrcpy(temp_name, driver->dependentfiles[i]);
1640                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1641                 }
1642         }
1643
1644         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1645
1646         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1647
1648         buf = NULL;
1649         len = buflen = 0;
1650
1651  again:
1652         len = 0;
1653         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1654                         driver->cversion,
1655                         driver->name,
1656                         driver->environment,
1657                         driver->driverpath,
1658                         driver->datafile,
1659                         driver->configfile,
1660                         driver->helpfile,
1661                         driver->monitorname,
1662                         driver->defaultdatatype);
1663
1664         if (driver->dependentfiles) {
1665                 for (i=0; *driver->dependentfiles[i]; i++) {
1666                         len += tdb_pack(buf+len, buflen-len, "f",
1667                                         driver->dependentfiles[i]);
1668                 }
1669         }
1670
1671         if (len != buflen) {
1672                 char *tb;
1673
1674                 tb = (char *)Realloc(buf, len);
1675                 if (!tb) {
1676                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1677                         ret = -1;
1678                         goto done;
1679                 }
1680                 else buf = tb;
1681                 buflen = len;
1682                 goto again;
1683         }
1684
1685
1686         kbuf.dptr = key;
1687         kbuf.dsize = strlen(key)+1;
1688         dbuf.dptr = buf;
1689         dbuf.dsize = len;
1690         
1691         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1692
1693 done:
1694         if (ret)
1695                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1696
1697         SAFE_FREE(buf);
1698         return ret;
1699 }
1700
1701 /****************************************************************************
1702 ****************************************************************************/
1703 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1704 {
1705         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1706
1707         ZERO_STRUCT(info3);
1708         info3.cversion = driver->version;
1709         fstrcpy(info3.name,driver->name);
1710         fstrcpy(info3.environment,driver->environment);
1711         fstrcpy(info3.driverpath,driver->driverpath);
1712         fstrcpy(info3.datafile,driver->datafile);
1713         fstrcpy(info3.configfile,driver->configfile);
1714         fstrcpy(info3.helpfile,driver->helpfile);
1715         fstrcpy(info3.monitorname,driver->monitorname);
1716         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1717         info3.dependentfiles = driver->dependentfiles;
1718
1719         return add_a_printer_driver_3(&info3);
1720 }
1721
1722
1723 /****************************************************************************
1724 ****************************************************************************/
1725 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1726 {
1727         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1728
1729         ZERO_STRUCT(info);
1730
1731         fstrcpy(info.name, driver);
1732         fstrcpy(info.defaultdatatype, "RAW");
1733         
1734         fstrcpy(info.driverpath, "");
1735         fstrcpy(info.datafile, "");
1736         fstrcpy(info.configfile, "");
1737         fstrcpy(info.helpfile, "");
1738
1739         if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1740                 return WERR_NOMEM;
1741
1742         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1743         fstrcpy(info.dependentfiles[0], "");
1744
1745         *info_ptr = memdup(&info, sizeof(info));
1746         
1747         return WERR_OK;
1748 }
1749
1750 /****************************************************************************
1751 ****************************************************************************/
1752 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1753 {
1754         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1755         TDB_DATA kbuf, dbuf;
1756         const char *architecture;
1757         int len = 0;
1758         int i;
1759         pstring key;
1760
1761         ZERO_STRUCT(driver);
1762
1763         architecture = get_short_archi(arch);
1764         
1765         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1766         
1767         if ( strcmp( arch, SPL_ARCH_WIN40 ) == 0 )
1768                 version = 0;
1769
1770         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1771
1772         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1773
1774         kbuf.dptr = key;
1775         kbuf.dsize = strlen(key)+1;
1776         
1777         dbuf = tdb_fetch(tdb_drivers, kbuf);
1778         if (!dbuf.dptr) 
1779                 return WERR_UNKNOWN_PRINTER_DRIVER;
1780
1781         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1782                           &driver.cversion,
1783                           driver.name,
1784                           driver.environment,
1785                           driver.driverpath,
1786                           driver.datafile,
1787                           driver.configfile,
1788                           driver.helpfile,
1789                           driver.monitorname,
1790                           driver.defaultdatatype);
1791
1792         i=0;
1793         while (len < dbuf.dsize) {
1794                 fstring *tddfs;
1795
1796                 tddfs = (fstring *)Realloc(driver.dependentfiles,
1797                                                          sizeof(fstring)*(i+2));
1798                 if (tddfs == NULL) {
1799                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1800                         break;
1801                 }
1802                 else driver.dependentfiles = tddfs;
1803
1804                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1805                                   &driver.dependentfiles[i]);
1806                 i++;
1807         }
1808         
1809         if (driver.dependentfiles != NULL)
1810                 fstrcpy(driver.dependentfiles[i], "");
1811
1812         SAFE_FREE(dbuf.dptr);
1813
1814         if (len != dbuf.dsize) {
1815                 SAFE_FREE(driver.dependentfiles);
1816
1817                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1818         }
1819
1820         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1821
1822         return WERR_OK;
1823 }
1824
1825 /****************************************************************************
1826  Debugging function, dump at level 6 the struct in the logs.
1827 ****************************************************************************/
1828
1829 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1830 {
1831         uint32 result;
1832         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1833         int i;
1834         
1835         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1836         
1837         switch (level)
1838         {
1839                 case 3:
1840                 {
1841                         if (driver.info_3 == NULL)
1842                                 result=5;
1843                         else {
1844                                 info3=driver.info_3;
1845                         
1846                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
1847                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
1848                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
1849                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
1850                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
1851                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
1852                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
1853                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
1854                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1855                                 
1856                                 for (i=0; info3->dependentfiles &&
1857                                           *info3->dependentfiles[i]; i++) {
1858                                         DEBUGADD(20,("dependentfile:[%s]\n",
1859                                                       info3->dependentfiles[i]));
1860                                 }
1861                                 result=0;
1862                         }
1863                         break;
1864                 }
1865                 default:
1866                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1867                         result=1;
1868                         break;
1869         }
1870         
1871         return result;
1872 }
1873
1874 /****************************************************************************
1875 ****************************************************************************/
1876 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1877 {
1878         int len = 0;
1879
1880         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1881
1882         if (!nt_devmode)
1883                 return len;
1884
1885         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1886                         nt_devmode->devicename,
1887                         nt_devmode->formname,
1888
1889                         nt_devmode->specversion,
1890                         nt_devmode->driverversion,
1891                         nt_devmode->size,
1892                         nt_devmode->driverextra,
1893                         nt_devmode->orientation,
1894                         nt_devmode->papersize,
1895                         nt_devmode->paperlength,
1896                         nt_devmode->paperwidth,
1897                         nt_devmode->scale,
1898                         nt_devmode->copies,
1899                         nt_devmode->defaultsource,
1900                         nt_devmode->printquality,
1901                         nt_devmode->color,
1902                         nt_devmode->duplex,
1903                         nt_devmode->yresolution,
1904                         nt_devmode->ttoption,
1905                         nt_devmode->collate,
1906                         nt_devmode->logpixels,
1907                         
1908                         nt_devmode->fields,
1909                         nt_devmode->bitsperpel,
1910                         nt_devmode->pelswidth,
1911                         nt_devmode->pelsheight,
1912                         nt_devmode->displayflags,
1913                         nt_devmode->displayfrequency,
1914                         nt_devmode->icmmethod,
1915                         nt_devmode->icmintent,
1916                         nt_devmode->mediatype,
1917                         nt_devmode->dithertype,
1918                         nt_devmode->reserved1,
1919                         nt_devmode->reserved2,
1920                         nt_devmode->panningwidth,
1921                         nt_devmode->panningheight,
1922                         nt_devmode->private);
1923
1924         
1925         if (nt_devmode->private) {
1926                 len += tdb_pack(buf+len, buflen-len, "B",
1927                                 nt_devmode->driverextra,
1928                                 nt_devmode->private);
1929         }
1930
1931         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1932
1933         return len;
1934 }
1935
1936 /****************************************************************************
1937  Pack all values in all printer keys
1938  ***************************************************************************/
1939  
1940 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1941 {
1942         int             len = 0;
1943         int             i, j;
1944         REGISTRY_VALUE  *val;
1945         REGVAL_CTR      *val_ctr;
1946         pstring         path;
1947         int             num_values;
1948
1949         if ( !data )
1950                 return 0;
1951
1952         /* loop over all keys */
1953                 
1954         for ( i=0; i<data->num_keys; i++ ) {    
1955                 val_ctr = &data->keys[i].values;
1956                 num_values = regval_ctr_numvals( val_ctr );
1957                 
1958                 /* loop over all values */
1959                 
1960                 for ( j=0; j<num_values; j++ ) {
1961                         /* pathname should be stored as <key>\<value> */
1962                         
1963                         val = regval_ctr_specific_value( val_ctr, j );
1964                         pstrcpy( path, data->keys[i].name );
1965                         pstrcat( path, "\\" );
1966                         pstrcat( path, regval_name(val) );
1967                         
1968                         len += tdb_pack(buf+len, buflen-len, "pPdB",
1969                                         val,
1970                                         path,
1971                                         regval_type(val),
1972                                         regval_size(val),
1973                                         regval_data_p(val) );
1974                 }
1975         
1976         }
1977
1978         /* terminator */
1979         
1980         len += tdb_pack(buf+len, buflen-len, "p", NULL);
1981
1982         return len;
1983 }
1984
1985
1986 /****************************************************************************
1987  Delete a printer - this just deletes the printer info file, any open
1988  handles are not affected.
1989 ****************************************************************************/
1990
1991 uint32 del_a_printer(char *sharename)
1992 {
1993         pstring key;
1994         TDB_DATA kbuf;
1995
1996         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1997
1998         kbuf.dptr=key;
1999         kbuf.dsize=strlen(key)+1;
2000
2001         tdb_delete(tdb_printers, kbuf);
2002         return 0;
2003 }
2004
2005 /* FIXME!!!  Reorder so this forward declaration is not necessary --jerry */
2006 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, const char* sharename);
2007 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2008 /****************************************************************************
2009 ****************************************************************************/
2010 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2011 {
2012         pstring key;
2013         char *buf;
2014         int buflen, len;
2015         WERROR ret;
2016         TDB_DATA kbuf, dbuf;
2017         
2018         /*
2019          * in addprinter: no servername and the printer is the name
2020          * in setprinter: servername is \\server
2021          *                and printer is \\server\\printer
2022          *
2023          * Samba manages only local printers.
2024          * we currently don't support things like path=\\other_server\printer
2025          */
2026
2027         if (info->servername[0]!='\0') {
2028                 trim_string(info->printername, info->servername, NULL);
2029                 trim_string(info->printername, "\\", NULL);
2030                 info->servername[0]='\0';
2031         }
2032
2033         /*
2034          * JFM: one day I'll forget.
2035          * below that's info->portname because that's the SAMBA sharename
2036          * and I made NT 'thinks' it's the portname
2037          * the info->sharename is the thing you can name when you add a printer
2038          * that's the short-name when you create shared printer for 95/98
2039          * So I've made a limitation in SAMBA: you can only have 1 printer model
2040          * behind a SAMBA share.
2041          */
2042
2043         buf = NULL;
2044         buflen = 0;
2045
2046  again: 
2047         len = 0;
2048         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2049                         info->attributes,
2050                         info->priority,
2051                         info->default_priority,
2052                         info->starttime,
2053                         info->untiltime,
2054                         info->status,
2055                         info->cjobs,
2056                         info->averageppm,
2057                         info->changeid,
2058                         info->c_setprinter,
2059                         info->setuptime,
2060                         info->servername,
2061                         info->printername,
2062                         info->sharename,
2063                         info->portname,
2064                         info->drivername,
2065                         info->comment,
2066                         info->location,
2067                         info->sepfile,
2068                         info->printprocessor,
2069                         info->datatype,
2070                         info->parameters);
2071
2072         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2073         
2074         len += pack_values( &info->data, buf+len, buflen-len );
2075
2076         if (buflen != len) {
2077                 char *tb;
2078
2079                 tb = (char *)Realloc(buf, len);
2080                 if (!tb) {
2081                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2082                         ret = WERR_NOMEM;
2083                         goto done;
2084                 }
2085                 else buf = tb;
2086                 buflen = len;
2087                 goto again;
2088         }
2089         
2090
2091         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2092
2093         kbuf.dptr = key;
2094         kbuf.dsize = strlen(key)+1;
2095         dbuf.dptr = buf;
2096         dbuf.dsize = len;
2097
2098         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2099
2100 done:
2101         if (!W_ERROR_IS_OK(ret))
2102                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2103
2104         SAFE_FREE(buf);
2105
2106         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2107                  info->sharename, info->drivername, info->portname, len));
2108
2109         return ret;
2110 }
2111
2112
2113 /****************************************************************************
2114  Malloc and return an NT devicemode.
2115 ****************************************************************************/
2116
2117 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2118 {
2119
2120         char adevice[MAXDEVICENAME];
2121         NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2122
2123         if (nt_devmode == NULL) {
2124                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2125                 return NULL;
2126         }
2127
2128         ZERO_STRUCTP(nt_devmode);
2129
2130         safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2131         fstrcpy(nt_devmode->devicename, adevice);       
2132         
2133         fstrcpy(nt_devmode->formname, "Letter");
2134
2135         nt_devmode->specversion      = 0x0401;
2136         nt_devmode->driverversion    = 0x0400;
2137         nt_devmode->size             = 0x00DC;
2138         nt_devmode->driverextra      = 0x0000;
2139         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2140                                        DEFAULTSOURCE | COPIES | SCALE |
2141                                        PAPERSIZE | ORIENTATION;
2142         nt_devmode->orientation      = 1;
2143         nt_devmode->papersize        = PAPER_LETTER;
2144         nt_devmode->paperlength      = 0;
2145         nt_devmode->paperwidth       = 0;
2146         nt_devmode->scale            = 0x64;
2147         nt_devmode->copies           = 1;
2148         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2149         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2150         nt_devmode->color            = COLOR_MONOCHROME;
2151         nt_devmode->duplex           = DUP_SIMPLEX;
2152         nt_devmode->yresolution      = 0;
2153         nt_devmode->ttoption         = TT_SUBDEV;
2154         nt_devmode->collate          = COLLATE_FALSE;
2155         nt_devmode->icmmethod        = 0;
2156         nt_devmode->icmintent        = 0;
2157         nt_devmode->mediatype        = 0;
2158         nt_devmode->dithertype       = 0;
2159
2160         /* non utilisés par un driver d'imprimante */
2161         nt_devmode->logpixels        = 0;
2162         nt_devmode->bitsperpel       = 0;
2163         nt_devmode->pelswidth        = 0;
2164         nt_devmode->pelsheight       = 0;
2165         nt_devmode->displayflags     = 0;
2166         nt_devmode->displayfrequency = 0;
2167         nt_devmode->reserved1        = 0;
2168         nt_devmode->reserved2        = 0;
2169         nt_devmode->panningwidth     = 0;
2170         nt_devmode->panningheight    = 0;
2171         
2172         nt_devmode->private = NULL;
2173         return nt_devmode;
2174 }
2175
2176 /****************************************************************************
2177  Deepcopy an NT devicemode.
2178 ****************************************************************************/
2179
2180 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2181 {
2182         NT_DEVICEMODE *new_nt_devicemode = NULL;
2183
2184         if ( !nt_devicemode )
2185                 return NULL;
2186
2187         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2188                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2189                 return NULL;
2190         }
2191
2192         new_nt_devicemode->private = NULL;
2193         if (nt_devicemode->private != NULL) {
2194                 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2195                         SAFE_FREE(new_nt_devicemode);
2196                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2197                         return NULL;
2198         }
2199         }
2200
2201         return new_nt_devicemode;
2202 }
2203
2204 /****************************************************************************
2205  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2206 ****************************************************************************/
2207
2208 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2209 {
2210         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2211
2212         if(nt_devmode == NULL)
2213                 return;
2214
2215         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2216
2217         SAFE_FREE(nt_devmode->private);
2218         SAFE_FREE(*devmode_ptr);
2219 }
2220
2221 /****************************************************************************
2222  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2223 ****************************************************************************/
2224 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2225 {
2226         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2227         NT_PRINTER_DATA         *data;
2228         int                     i;
2229
2230         if ( !info )
2231                 return;
2232
2233         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2234
2235         free_nt_devicemode(&info->devmode);
2236
2237         /* clean up all registry keys */
2238         
2239         data = &info->data;
2240         for ( i=0; i<data->num_keys; i++ ) {
2241                 SAFE_FREE( data->keys[i].name );
2242                 regval_ctr_destroy( &data->keys[i].values );
2243         }
2244         SAFE_FREE( data->keys );
2245
2246         /* finally the top level structure */
2247         
2248         SAFE_FREE( *info_ptr );
2249 }
2250
2251
2252 /****************************************************************************
2253 ****************************************************************************/
2254 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2255 {
2256         int len = 0;
2257         int extra_len = 0;
2258         NT_DEVICEMODE devmode;
2259
2260         ZERO_STRUCT(devmode);
2261
2262         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2263
2264         if (!*nt_devmode) return len;
2265
2266         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2267                           devmode.devicename,
2268                           devmode.formname,
2269
2270                           &devmode.specversion,
2271                           &devmode.driverversion,
2272                           &devmode.size,
2273                           &devmode.driverextra,
2274                           &devmode.orientation,
2275                           &devmode.papersize,
2276                           &devmode.paperlength,
2277                           &devmode.paperwidth,
2278                           &devmode.scale,
2279                           &devmode.copies,
2280                           &devmode.defaultsource,
2281                           &devmode.printquality,
2282                           &devmode.color,
2283                           &devmode.duplex,
2284                           &devmode.yresolution,
2285                           &devmode.ttoption,
2286                           &devmode.collate,
2287                           &devmode.logpixels,
2288                         
2289                           &devmode.fields,
2290                           &devmode.bitsperpel,
2291                           &devmode.pelswidth,
2292                           &devmode.pelsheight,
2293                           &devmode.displayflags,
2294                           &devmode.displayfrequency,
2295                           &devmode.icmmethod,
2296                           &devmode.icmintent,
2297                           &devmode.mediatype,
2298                           &devmode.dithertype,
2299                           &devmode.reserved1,
2300                           &devmode.reserved2,
2301                           &devmode.panningwidth,
2302                           &devmode.panningheight,
2303                           &devmode.private);
2304         
2305         if (devmode.private) {
2306                 /* the len in tdb_unpack is an int value and
2307                  * devmode.driverextra is only a short
2308                  */
2309                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2310                 devmode.driverextra=(uint16)extra_len;
2311                 
2312                 /* check to catch an invalid TDB entry so we don't segfault */
2313                 if (devmode.driverextra == 0) {
2314                         devmode.private = NULL;
2315                 }
2316         }
2317
2318         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2319
2320         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2321         if (devmode.private)
2322                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2323
2324         return len;
2325 }
2326
2327 /****************************************************************************
2328  Allocate and initialize a new slot.
2329 ***************************************************************************/
2330  
2331 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2332 {
2333         NT_PRINTER_KEY  *d;
2334         int             key_index;
2335         
2336         if ( !data || !name )
2337                 return -1;
2338         
2339         /* allocate another slot in the NT_PRINTER_KEY array */
2340         
2341         d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2342         if ( d )
2343                 data->keys = d;
2344         
2345         key_index = data->num_keys;
2346         
2347         /* initialze new key */
2348         
2349         data->num_keys++;
2350         data->keys[key_index].name = strdup( name );
2351         
2352         ZERO_STRUCTP( &data->keys[key_index].values );
2353         
2354         regval_ctr_init( &data->keys[key_index].values );
2355         
2356         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2357         
2358         return key_index;
2359 }
2360
2361 /****************************************************************************
2362  search for a registry key name in the existing printer data
2363  ***************************************************************************/
2364  
2365 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2366 {
2367         int             key_index = -1;
2368         int             i;
2369         
2370         if ( !data || !name )
2371                 return -1;
2372
2373         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2374
2375         /* loop over all existing keys */
2376         
2377         for ( i=0; i<data->num_keys; i++ ) {
2378                 if ( strequal(data->keys[i].name, name) ) {
2379                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2380                         key_index = i;
2381                         break;
2382                 
2383                 }
2384         }
2385         
2386         return key_index;
2387 }
2388
2389 /****************************************************************************
2390  ***************************************************************************/
2391
2392 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2393 {
2394         int     i, j;
2395         int     key_len;
2396         int     num_subkeys = 0;
2397         char    *p;
2398         fstring *ptr, *subkeys_ptr = NULL;
2399         fstring subkeyname;
2400         
2401         if ( !data )
2402                 return 0;
2403                 
2404         for ( i=0; i<data->num_keys; i++ ) {
2405                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2406                         /* match sure it is a subkey and not the key itself */
2407                         
2408                         key_len = strlen( key );
2409                         if ( strlen(data->keys[i].name) == key_len )
2410                                 continue;
2411                         
2412                         /* get subkey path */
2413
2414                         p = data->keys[i].name + key_len;
2415                         if ( *p == '\\' )
2416                                 p++;
2417                         fstrcpy( subkeyname, p );
2418                         if ( (p = strchr( subkeyname, '\\' )) )
2419                                 *p = '\0';
2420                         
2421                         /* don't add a key more than once */
2422                         
2423                         for ( j=0; j<num_subkeys; j++ ) {
2424                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2425                                         break;
2426                         }
2427                         
2428                         if ( j != num_subkeys )
2429                                 continue;
2430
2431                         /* found a match, so allocate space and copy the name */
2432                         
2433                         if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2434                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2435                                         num_subkeys+1));
2436                                 SAFE_FREE( subkeys );
2437                                 return 0;
2438                         }
2439                         
2440                         subkeys_ptr = ptr;
2441                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2442                         num_subkeys++;
2443                 }
2444                 
2445         }
2446         
2447         /* tag of the end */
2448         
2449         if (num_subkeys)
2450                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2451         
2452         *subkeys = subkeys_ptr;
2453
2454         return num_subkeys;
2455 }
2456
2457 #ifdef HAVE_ADS
2458 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2459                             const char *sz)
2460 {
2461         smb_ucs2_t conv_str[1024];
2462         size_t str_size;
2463
2464         regval_ctr_delvalue(ctr, val_name);
2465         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2466                              STR_TERMINATE | STR_NOALIGN);
2467         regval_ctr_addvalue(ctr, val_name, REG_SZ, 
2468                             (char *) conv_str, str_size);
2469 }
2470
2471 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2472                                uint32 dword)
2473 {
2474         regval_ctr_delvalue(ctr, val_name);
2475         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2476                             (char *) &dword, sizeof(dword));
2477 }
2478
2479 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2480                               BOOL b)
2481 {
2482         uint8 bin_bool = (b ? 1 : 0);
2483         regval_ctr_delvalue(ctr, val_name);
2484         regval_ctr_addvalue(ctr, val_name, REG_BINARY, 
2485                             (char *) &bin_bool, sizeof(bin_bool));
2486 }
2487
2488 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2489                                          const char *multi_sz)
2490 {
2491         smb_ucs2_t *conv_strs = NULL;
2492         size_t str_size;
2493
2494         /* a multi-sz has to have a null string terminator, i.e., the last
2495            string must be followed by two nulls */
2496         str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2497         conv_strs = calloc(str_size, 1);
2498
2499         push_ucs2(NULL, conv_strs, multi_sz, str_size, 
2500                   STR_TERMINATE | STR_NOALIGN);
2501
2502         regval_ctr_delvalue(ctr, val_name);
2503         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ, 
2504                             (char *) conv_strs, str_size);      
2505         safe_free(conv_strs);
2506         
2507 }
2508
2509 /****************************************************************************
2510  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2511  *
2512  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2513  * @return BOOL indicating success or failure
2514  ***************************************************************************/
2515
2516 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2517 {
2518         REGVAL_CTR *ctr = NULL;
2519         fstring longname;
2520         char *allocated_string = NULL;
2521         const char *ascii_str;
2522         int i;
2523
2524         if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2525                 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2526         ctr = &info2->data.keys[i].values;
2527
2528         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2529         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2530
2531         get_myfullname(longname);
2532         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2533
2534         asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2535         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2536         SAFE_FREE(allocated_string);
2537
2538         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2539         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2540         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2541         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2542         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2543         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2544         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2545         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2546         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2547
2548         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2549                           (info2->attributes & 
2550                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2551
2552         switch (info2->attributes & 0x3) {
2553         case 0:
2554                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2555                 break;
2556         case 1:
2557                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2558                 break;
2559         case 2:
2560                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2561                 break;
2562         default:
2563                 ascii_str = "unknown";
2564         }
2565         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2566
2567         return True;
2568 }
2569
2570 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, GUID guid)
2571 {
2572         int i;
2573         REGVAL_CTR *ctr=NULL;
2574
2575         /* find the DsSpooler key */
2576         if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2577                 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2578         ctr = &info2->data.keys[i].values;
2579
2580         regval_ctr_delvalue(ctr, "objectGUID");
2581         regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY, 
2582                             (char *) &guid, sizeof(GUID));      
2583 }
2584
2585 static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2586 {
2587         ADS_STATUS ads_rc;
2588         TALLOC_CTX *ctx = talloc_init("publish_it");
2589         ADS_MODLIST mods = ads_init_mods(ctx);
2590         char *prt_dn = NULL, *srv_dn, **srv_cn;
2591         void *res = NULL;
2592         ADS_STRUCT *ads;
2593         const char *attrs[] = {"objectGUID", NULL};
2594         GUID guid;
2595         WERROR win_rc = WERR_OK;
2596
2597         ZERO_STRUCT(guid);
2598         /* set the DsSpooler info and attributes */
2599         if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2600                         return WERR_NOMEM;
2601         printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2602         win_rc = mod_a_printer(*printer, 2);
2603         if (!W_ERROR_IS_OK(win_rc)) {
2604                 DEBUG(3, ("err %d saving data\n",
2605                                   W_ERROR_V(win_rc)));
2606                 return win_rc;
2607         }
2608
2609         /* Build the ads mods */
2610         get_local_printer_publishing_data(ctx, &mods, 
2611                                           &printer->info_2->data);
2612         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, 
2613                     printer->info_2->sharename);
2614
2615         /* initial ads structure */
2616         
2617         ads = ads_init(NULL, NULL, NULL);
2618         if (!ads) {
2619                 DEBUG(3, ("ads_init() failed\n"));
2620                 return WERR_SERVER_UNAVAILABLE;
2621         }
2622         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2623         SAFE_FREE(ads->auth.password);
2624         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2625                 NULL, NULL);
2626                 
2627         /* ads_connect() will find the DC for us */                                         
2628         ads_rc = ads_connect(ads);
2629         if (!ADS_ERR_OK(ads_rc)) {
2630                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2631                 ads_destroy(&ads);
2632                 return WERR_ACCESS_DENIED;
2633         }
2634
2635         /* figure out where to publish */
2636         ads_find_machine_acct(ads, &res, global_myname());
2637         srv_dn = ldap_get_dn(ads->ld, res);
2638         ads_msgfree(ads, res);
2639         srv_cn = ldap_explode_dn(srv_dn, 1);
2640         asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], 
2641                  printer->info_2->sharename, srv_dn);
2642         ads_memfree(ads, srv_dn);
2643
2644         /* publish it */
2645         ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2646         if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2647                 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2648         
2649         /* retreive the guid and store it locally */
2650         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2651                 ads_memfree(ads, prt_dn);
2652                 ads_pull_guid(ads, res, &guid);
2653                 ads_msgfree(ads, res);
2654                 store_printer_guid(printer->info_2, guid);
2655                 win_rc = mod_a_printer(*printer, 2);
2656         } 
2657
2658         safe_free(prt_dn);
2659         ads_destroy(&ads);
2660
2661         return WERR_OK;
2662 }
2663
2664 WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2665 {
2666         ADS_STATUS ads_rc;
2667         ADS_STRUCT *ads;
2668         void *res;
2669         char *prt_dn = NULL;
2670         WERROR win_rc;
2671
2672         printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2673         win_rc = mod_a_printer(*printer, 2);
2674         if (!W_ERROR_IS_OK(win_rc)) {
2675                 DEBUG(3, ("err %d saving data\n",
2676                                   W_ERROR_V(win_rc)));
2677                 return win_rc;
2678         }
2679         
2680         ads = ads_init(NULL, NULL, NULL);
2681         if (!ads) {
2682                 DEBUG(3, ("ads_init() failed\n"));
2683                 return WERR_SERVER_UNAVAILABLE;
2684         }
2685         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2686         SAFE_FREE(ads->auth.password);
2687         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2688                 NULL, NULL);
2689
2690         /* ads_connect() will find the DC for us */                                         
2691         ads_rc = ads_connect(ads);
2692         if (!ADS_ERR_OK(ads_rc)) {
2693                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2694                 ads_destroy(&ads);
2695                 return WERR_ACCESS_DENIED;
2696         }
2697         
2698         /* remove the printer from the directory */
2699         ads_rc = ads_find_printer_on_server(ads, &res, 
2700                             printer->info_2->sharename, global_myname());
2701         if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2702                 prt_dn = ads_get_dn(ads, res);
2703                 ads_msgfree(ads, res);
2704                 ads_rc = ads_del_dn(ads, prt_dn);
2705                 ads_memfree(ads, prt_dn);
2706         }
2707
2708         ads_destroy(&ads);
2709         return WERR_OK;
2710 }
2711
2712 /****************************************************************************
2713  * Publish a printer in the directory
2714  *
2715  * @param snum describing printer service
2716  * @return WERROR indicating status of publishing
2717  ***************************************************************************/
2718
2719 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2720 {
2721         NT_PRINTER_INFO_LEVEL *printer = NULL;
2722         WERROR win_rc;
2723
2724         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2725         if (!W_ERROR_IS_OK(win_rc))
2726                 return win_rc;
2727
2728         switch(action) {
2729         case SPOOL_DS_PUBLISH:
2730         case SPOOL_DS_UPDATE:
2731                 win_rc = publish_it(printer);
2732                 break;
2733         case SPOOL_DS_UNPUBLISH:
2734                 win_rc = unpublish_it(printer);
2735                 break;
2736         default:
2737                 win_rc = WERR_NOT_SUPPORTED;
2738         }
2739         
2740
2741         free_a_printer(&printer, 2);
2742         return win_rc;
2743 }
2744
2745 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2746 {
2747         NT_PRINTER_INFO_LEVEL *printer = NULL;
2748         REGVAL_CTR *ctr;
2749         REGISTRY_VALUE *guid_val;
2750         WERROR win_rc;
2751         int i;
2752
2753
2754         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2755         if (!W_ERROR_IS_OK(win_rc))
2756                 return False;
2757
2758         if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2759                 return False;
2760
2761         if ((i = lookup_printerkey(&printer->info_2->data, 
2762                                    SPOOL_DSSPOOLER_KEY)) < 0)
2763                 return False;
2764
2765         if (!(ctr = &printer->info_2->data.keys[i].values)) {
2766                 return False;
2767         }
2768
2769         if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2770                 return False;
2771         }
2772
2773         if (regval_size(guid_val) == sizeof(GUID))
2774                 memcpy(guid, regval_data_p(guid_val), sizeof(GUID));
2775
2776         return True;
2777 }
2778         
2779 #else
2780 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2781 {
2782         return WERR_OK;
2783 }
2784 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2785 {
2786         return False;
2787 }
2788 #endif
2789 /****************************************************************************
2790  ***************************************************************************/
2791  
2792 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2793 {
2794         NT_PRINTER_DATA *data;
2795         int             i;
2796         int             removed_keys = 0;
2797         int             empty_slot;
2798         
2799         data = &p2->data;
2800         empty_slot = data->num_keys;
2801
2802         if ( !key )
2803                 return WERR_INVALID_PARAM;
2804         
2805         /* remove all keys */
2806
2807         if ( !strlen(key) ) {
2808                 for ( i=0; i<data->num_keys; i++ ) {
2809                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2810                                 data->keys[i].name));
2811                 
2812                         SAFE_FREE( data->keys[i].name );
2813                         regval_ctr_destroy( &data->keys[i].values );
2814                 }
2815         
2816                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2817                         p2->printername ));
2818         
2819                 SAFE_FREE( data->keys );
2820                 ZERO_STRUCTP( data );
2821
2822                 return WERR_OK;
2823         }
2824
2825         /* remove a specific key (and all subkeys) */
2826         
2827         for ( i=0; i<data->num_keys; i++ ) {
2828                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2829                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2830                                 data->keys[i].name));
2831                 
2832                         SAFE_FREE( data->keys[i].name );
2833                         regval_ctr_destroy( &data->keys[i].values );
2834                 
2835                         /* mark the slot as empty */
2836
2837                         ZERO_STRUCTP( &data->keys[i] );
2838                 }
2839         }
2840
2841         /* find the first empty slot */
2842
2843         for ( i=0; i<data->num_keys; i++ ) {
2844                 if ( !data->keys[i].name ) {
2845                         empty_slot = i;
2846                         removed_keys++;
2847                         break;
2848                 }
2849         }
2850
2851         if ( i == data->num_keys )
2852                 /* nothing was removed */
2853                 return WERR_INVALID_PARAM;
2854
2855         /* move everything down */
2856         
2857         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2858                 if ( data->keys[i].name ) {
2859                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
2860                         ZERO_STRUCTP( &data->keys[i] );
2861                         empty_slot++;
2862                         removed_keys++;
2863                 }
2864         }
2865
2866         /* update count */
2867                 
2868         data->num_keys -= removed_keys;
2869
2870         /* sanity check to see if anything is left */
2871
2872         if ( !data->num_keys ) {
2873                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2874
2875                 SAFE_FREE( data->keys );
2876                 ZERO_STRUCTP( data );
2877         }
2878
2879         return WERR_OK;
2880 }
2881
2882 /****************************************************************************
2883  ***************************************************************************/
2884  
2885 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2886 {
2887         WERROR          result = WERR_OK;
2888         int             key_index;
2889         
2890         /* we must have names on non-zero length */
2891         
2892         if ( !key || !*key|| !value || !*value )
2893                 return WERR_INVALID_NAME;
2894                 
2895         /* find the printer key first */
2896
2897         key_index = lookup_printerkey( &p2->data, key );
2898         if ( key_index == -1 )
2899                 return WERR_OK;
2900                 
2901         regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2902         
2903         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2904                 key, value ));
2905         
2906         return result;
2907 }
2908
2909 /****************************************************************************
2910  ***************************************************************************/
2911  
2912 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
2913                            uint32 type, uint8 *data, int real_len )
2914 {
2915         WERROR          result = WERR_OK;
2916         int             key_index;
2917
2918         /* we must have names on non-zero length */
2919         
2920         if ( !key || !*key|| !value || !*value )
2921                 return WERR_INVALID_NAME;
2922                 
2923         /* find the printer key first */
2924         
2925         key_index = lookup_printerkey( &p2->data, key );
2926         if ( key_index == -1 )
2927                 key_index = add_new_printer_key( &p2->data, key );
2928                 
2929         if ( key_index == -1 )
2930                 return WERR_NOMEM;
2931         
2932         regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2933                 type, data, real_len );
2934         
2935         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2936                 key, value, type, real_len  ));
2937         
2938         return result;
2939 }
2940
2941 /****************************************************************************
2942  ***************************************************************************/
2943  
2944 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2945 {
2946         int             key_index;
2947
2948         if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2949                 return NULL;
2950
2951         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2952                 key, value ));
2953
2954         return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
2955 }
2956
2957 /****************************************************************************
2958  Unpack a list of registry values frem the TDB
2959  ***************************************************************************/
2960  
2961 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
2962 {
2963         int             len = 0;
2964         uint32          type;
2965         pstring         string, valuename, keyname;
2966         char            *str;
2967         int             size;
2968         uint8           *data_p;
2969         REGISTRY_VALUE  *regval_p;
2970         int             key_index;
2971         
2972         /* add the "PrinterDriverData" key first for performance reasons */
2973         
2974         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
2975
2976         /* loop and unpack the rest of the registry values */
2977         
2978         while ( True ) {
2979         
2980                 /* check to see if there are any more registry values */
2981                 
2982                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
2983                 if ( !regval_p ) 
2984                         break;
2985
2986                 /* unpack the next regval */
2987                 
2988                 len += tdb_unpack(buf+len, buflen-len, "fdB",
2989                                   string,
2990                                   &type,
2991                                   &size,
2992                                   &data_p);
2993         
2994                 /*
2995                  * break of the keyname from the value name.  
2996                  * Should only be one '\' in the string returned.
2997                  */     
2998                  
2999                 str = strrchr( string, '\\');
3000                 
3001                 /* Put in "PrinterDriverData" is no key specified */
3002                 
3003                 if ( !str ) {
3004                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3005                         pstrcpy( valuename, string );
3006                 }
3007                 else {
3008                         *str = '\0';
3009                         pstrcpy( keyname, string );
3010                         pstrcpy( valuename, str+1 );
3011                 }
3012                         
3013                 /* see if we need a new key */
3014                 
3015                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3016                         key_index = add_new_printer_key( printer_data, keyname );
3017                         
3018                 if ( key_index == -1 ) {
3019                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3020                                 keyname));
3021                         break;
3022                 }
3023                 
3024                 /* add the new value */
3025                 
3026                 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size );
3027
3028                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3029
3030                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3031         }
3032
3033         return len;
3034 }
3035
3036 /****************************************************************************
3037  ***************************************************************************/
3038
3039 static void map_to_os2_driver(fstring drivername)
3040 {
3041         static BOOL initialised=False;
3042         static fstring last_from,last_to;
3043         char *mapfile = lp_os2_driver_map();
3044         char **lines = NULL;
3045         int numlines = 0;
3046         int i;
3047
3048         if (!strlen(drivername))
3049                 return;
3050
3051         if (!*mapfile)
3052                 return;
3053
3054         if (!initialised) {
3055                 *last_from = *last_to = 0;
3056                 initialised = True;
3057         }
3058
3059         if (strequal(drivername,last_from)) {
3060                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3061                 fstrcpy(drivername,last_to);
3062                 return;
3063         }
3064
3065         lines = file_lines_load(mapfile, &numlines);
3066         if (numlines == 0) {
3067                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3068                 return;
3069         }
3070
3071         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3072
3073         for( i = 0; i < numlines; i++) {
3074                 char *nt_name = lines[i];
3075                 char *os2_name = strchr(nt_name,'=');
3076
3077                 if (!os2_name)
3078                         continue;
3079
3080                 *os2_name++ = 0;
3081
3082                 while (isspace(*nt_name))
3083                         nt_name++;
3084
3085                 if (!*nt_name || strchr("#;",*nt_name))
3086                         continue;
3087
3088                 {
3089                         int l = strlen(nt_name);
3090                         while (l && isspace(nt_name[l-1])) {
3091                                 nt_name[l-1] = 0;
3092                                 l--;
3093                         }
3094                 }
3095
3096                 while (isspace(*os2_name))
3097                         os2_name++;
3098
3099                 {
3100                         int l = strlen(os2_name);
3101                         while (l && isspace(os2_name[l-1])) {
3102                                 os2_name[l-1] = 0;
3103                                 l--;
3104                         }
3105                 }
3106
3107                 if (strequal(nt_name,drivername)) {
3108                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3109                         fstrcpy(last_from,drivername);
3110                         fstrcpy(last_to,os2_name);
3111                         fstrcpy(drivername,os2_name);
3112                         file_lines_free(lines);
3113                         return;
3114                 }
3115         }
3116
3117         file_lines_free(lines);
3118 }
3119
3120 /****************************************************************************
3121  Get a default printer info 2 struct.
3122 ****************************************************************************/
3123 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3124 {
3125         int snum;
3126         NT_PRINTER_INFO_LEVEL_2 info;
3127
3128         ZERO_STRUCT(info);
3129
3130         snum = lp_servicenumber(sharename);
3131
3132         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3133         slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
3134                  get_called_name(), sharename);
3135         fstrcpy(info.sharename, sharename);
3136         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3137
3138         /* by setting the driver name to an empty string, a local NT admin
3139            can now run the **local** APW to install a local printer driver
3140            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3141            installed on the Samba server for NT clients --jerry */
3142 #if 0   /* JERRY --do not uncomment-- */
3143         if (!*info.drivername)
3144                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3145 #endif
3146
3147
3148         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3149
3150         pstrcpy(info.comment, "");
3151         fstrcpy(info.printprocessor, "winprint");
3152         fstrcpy(info.datatype, "RAW");
3153
3154         info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3155
3156         info.starttime = 0; /* Minutes since 12:00am GMT */
3157         info.untiltime = 0; /* Minutes since 12:00am GMT */
3158         info.priority = 1;
3159         info.default_priority = 1;
3160         info.setuptime = (uint32)time(NULL);
3161
3162         /*
3163          * I changed this as I think it is better to have a generic
3164          * DEVMODE than to crash Win2k explorer.exe   --jerry
3165          * See the HP Deskjet 990c Win2k drivers for an example.
3166          *
3167          * However the default devmode appears to cause problems
3168          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3169          * the "default devmode" parameter   --jerry 22/01/2002
3170          */
3171
3172         if (lp_default_devmode(snum)) {
3173                 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3174                         goto fail;
3175         }
3176         else {
3177                 info.devmode = NULL;
3178         }
3179
3180         /* This will get the current RPC talloc context, but we should be
3181            passing this as a parameter... fixme... JRA ! */
3182
3183         if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3184                 goto fail;
3185
3186         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3187         if (! *info_ptr) {
3188                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3189                 goto fail;
3190         }
3191
3192         return WERR_OK;
3193
3194   fail:
3195         if (info.devmode)
3196                 free_nt_devicemode(&info.devmode);
3197         return WERR_ACCESS_DENIED;
3198 }
3199
3200 /****************************************************************************
3201 ****************************************************************************/
3202 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3203 {
3204         pstring key;
3205         NT_PRINTER_INFO_LEVEL_2 info;
3206         int             len = 0;
3207         TDB_DATA kbuf, dbuf;
3208         fstring printername;
3209                 
3210         ZERO_STRUCT(info);
3211
3212         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3213
3214         kbuf.dptr = key;
3215         kbuf.dsize = strlen(key)+1;
3216
3217         dbuf = tdb_fetch(tdb_printers, kbuf);
3218         if (!dbuf.dptr)
3219                 return get_a_printer_2_default(info_ptr, sharename);
3220
3221         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3222                         &info.attributes,
3223                         &info.priority,
3224                         &info.default_priority,
3225                         &info.starttime,
3226                         &info.untiltime,
3227                         &info.status,
3228                         &info.cjobs,
3229                         &info.averageppm,
3230                         &info.changeid,
3231                         &info.c_setprinter,
3232                         &info.setuptime,
3233                         info.servername,
3234                         info.printername,
3235                         info.sharename,
3236                         info.portname,
3237                         info.drivername,
3238                         info.comment,
3239                         info.location,
3240                         info.sepfile,
3241                         info.printprocessor,
3242                         info.datatype,
3243                         info.parameters);
3244
3245         /* Samba has to have shared raw drivers. */
3246         info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3247
3248         /* Restore the stripped strings. */
3249         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3250         slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3251                         info.printername);
3252         fstrcpy(info.printername, printername);
3253
3254         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3255
3256         /*
3257          * Some client drivers freak out if there is a NULL devmode
3258          * (probably the driver is not checking before accessing 
3259          * the devmode pointer)   --jerry
3260          *
3261          * See comments in get_a_printer_2_default()
3262          */
3263
3264         if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3265                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3266                         printername));
3267                 info.devmode = construct_nt_devicemode(printername);
3268         }
3269
3270         len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3271
3272         /* This will get the current RPC talloc context, but we should be
3273            passing this as a parameter... fixme... JRA ! */
3274
3275         nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3276
3277         /* Fix for OS/2 drivers. */
3278
3279         if (get_remote_arch() == RA_OS2)
3280                 map_to_os2_driver(info.drivername);
3281
3282         SAFE_FREE(dbuf.dptr);
3283         *info_ptr=memdup(&info, sizeof(info));
3284
3285         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3286                  sharename, info.printername, info.drivername));
3287
3288         return WERR_OK; 
3289 }
3290
3291 /****************************************************************************
3292  Debugging function, dump at level 6 the struct in the logs.
3293 ****************************************************************************/
3294 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3295 {
3296         uint32 result;
3297         NT_PRINTER_INFO_LEVEL_2 *info2;
3298         
3299         DEBUG(106,("Dumping printer at level [%d]\n", level));
3300         
3301         switch (level) {
3302                 case 2:
3303                 {
3304                         if (printer.info_2 == NULL)
3305                                 result=5;
3306                         else
3307                         {
3308                                 info2=printer.info_2;
3309                         
3310                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3311                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3312                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3313                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3314                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3315                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3316                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3317                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3318                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3319                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3320                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3321
3322                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3323                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3324                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3325                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3326                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3327                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3328                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3329                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3330                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3331                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3332                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3333                                 result=0;
3334                         }
3335                         break;
3336                 }
3337                 default:
3338                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3339                         result=1;
3340                         break;
3341         }
3342         
3343         return result;
3344 }
3345
3346 /****************************************************************************
3347  Update the changeid time.
3348  This is SO NASTY as some drivers need this to change, others need it
3349  static. This value will change every second, and I must hope that this
3350  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3351  UTAH ! JRA.
3352 ****************************************************************************/
3353
3354 static uint32 rev_changeid(void)
3355 {
3356         struct timeval tv;
3357
3358         get_process_uptime(&tv);
3359
3360 #if 1   /* JERRY */
3361         /* Return changeid as msec since spooler restart */
3362         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3363 #else
3364         /*
3365          * This setting seems to work well but is too untested
3366          * to replace the above calculation.  Left in for experiementation
3367          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3368          */
3369         return tv.tv_sec * 10 + tv.tv_usec / 100000;
3370 #endif
3371 }
3372
3373 /*
3374  * The function below are the high level ones.
3375  * only those ones must be called from the spoolss code.
3376  * JFM.
3377  */
3378
3379 /****************************************************************************
3380  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3381 ****************************************************************************/
3382
3383 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3384 {
3385         WERROR result;
3386         
3387         dump_a_printer(printer, level); 
3388         
3389         /* 
3390          * invalidate cache for all open handles to this printer.
3391          * cache for a given handle will be updated on the next 
3392          * get_a_printer() 
3393          */
3394          
3395         invalidate_printer_hnd_cache( printer.info_2->sharename );
3396         
3397         switch (level) {
3398                 case 2:
3399                 {
3400                         /*
3401                          * Update the changestamp.  Emperical tests show that the
3402                          * ChangeID is always updated,but c_setprinter is  
3403                          *  global spooler variable (not per printer).
3404                          */
3405
3406                         /* ChangeID **must** be increasing over the lifetime
3407                            of client's spoolss service in order for the
3408                            client's cache to show updates */
3409
3410                         printer.info_2->changeid = rev_changeid();
3411
3412                         /*
3413                          * Because one day someone will ask:
3414                          * NT->NT       An admin connection to a remote
3415                          *              printer show changes imeediately in
3416                          *              the properities dialog
3417                          *      
3418                          *              A non-admin connection will only show the
3419                          *              changes after viewing the properites page
3420                          *              2 times.  Seems to be related to a
3421                          *              race condition in the client between the spooler
3422                          *              updating the local cache and the Explorer.exe GUI
3423                          *              actually displaying the properties.
3424                          *
3425                          *              This is fixed in Win2k.  admin/non-admin
3426                          *              connections both display changes immediately.
3427                          *
3428                          * 14/12/01     --jerry
3429                          */
3430
3431                         result=update_a_printer_2(printer.info_2);
3432                         
3433                         break;
3434                 }
3435                 default:
3436                         result=WERR_UNKNOWN_LEVEL;
3437                         break;
3438         }
3439         
3440         return result;
3441 }
3442
3443 /****************************************************************************
3444  Initialize printer devmode & data with previously saved driver init values.
3445 ****************************************************************************/
3446
3447 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3448 {
3449         int                     len = 0;
3450         pstring                 key;
3451         TDB_DATA                kbuf, dbuf;
3452         NT_PRINTER_INFO_LEVEL_2 info;
3453
3454
3455         ZERO_STRUCT(info);
3456
3457         /*
3458          * Delete any printer data 'values' already set. When called for driver
3459          * replace, there will generally be some, but during an add printer, there
3460          * should not be any (if there are delete them).
3461          */
3462          
3463         delete_all_printer_data( info_ptr, "" );
3464         
3465         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3466
3467         kbuf.dptr = key;
3468         kbuf.dsize = strlen(key)+1;
3469
3470         dbuf = tdb_fetch(tdb_drivers, kbuf);
3471         if (!dbuf.dptr) {
3472                 /*
3473                  * When changing to a driver that has no init info in the tdb, remove
3474                  * the previous drivers init info and leave the new on blank.
3475                  */
3476                 free_nt_devicemode(&info_ptr->devmode);
3477                 return False;
3478         }
3479         
3480         /*
3481          * Get the saved DEVMODE..
3482          */
3483          
3484         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3485
3486         /*
3487          * The saved DEVMODE contains the devicename from the printer used during
3488          * the initialization save. Change it to reflect the new printer.
3489          */
3490          
3491         if ( info.devmode ) {
3492                 ZERO_STRUCT(info.devmode->devicename);
3493                 fstrcpy(info.devmode->devicename, info_ptr->printername);
3494         }
3495
3496         /*
3497          * NT/2k does not change out the entire DeviceMode of a printer
3498          * when changing the driver.  Only the driverextra, private, & 
3499          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3500          *
3501          * Later examination revealed that Windows NT/2k does reset the
3502          * the printer's device mode, bit **only** when you change a 
3503          * property of the device mode such as the page orientation.
3504          * --jerry
3505          */
3506
3507
3508         /* Bind the saved DEVMODE to the new the printer */
3509          
3510         free_nt_devicemode(&info_ptr->devmode);
3511         info_ptr->devmode = info.devmode;
3512
3513         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3514                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3515
3516         /* Add the printer data 'values' to the new printer */
3517          
3518         len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3519         
3520
3521         SAFE_FREE(dbuf.dptr);
3522
3523         return True;    
3524 }
3525
3526 /****************************************************************************
3527  Initialize printer devmode & data with previously saved driver init values.
3528  When a printer is created using AddPrinter, the drivername bound to the
3529  printer is used to lookup previously saved driver initialization info, which
3530  is bound to the new printer.
3531 ****************************************************************************/
3532
3533 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3534 {
3535         BOOL result = False;
3536         
3537         switch (level) {
3538                 case 2:
3539                         result = set_driver_init_2(printer->info_2);
3540                         break;
3541                         
3542                 default:
3543                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
3544                                 level));
3545                         break;
3546         }
3547         
3548         return result;
3549 }
3550
3551 /****************************************************************************
3552  Delete driver init data stored for a specified driver
3553 ****************************************************************************/
3554
3555 BOOL del_driver_init(char *drivername)
3556 {
3557         pstring key;
3558         TDB_DATA kbuf;
3559
3560         if (!drivername || !*drivername) {
3561                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3562                 return False;
3563         }
3564
3565         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3566
3567         kbuf.dptr = key;
3568         kbuf.dsize = strlen(key)+1;
3569
3570         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3571
3572         return (tdb_delete(tdb_drivers, kbuf) == 0);
3573 }
3574
3575 /****************************************************************************
3576  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
3577  in the tdb. Note: this is different from the driver entry and the printer
3578  entry. There should be a single driver init entry for each driver regardless
3579  of whether it was installed from NT or 2K. Technically, they should be
3580  different, but they work out to the same struct.
3581 ****************************************************************************/
3582
3583 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3584 {
3585         pstring key;
3586         char *buf;
3587         int buflen, len, ret;
3588         TDB_DATA kbuf, dbuf;
3589
3590         buf = NULL;
3591         buflen = 0;
3592
3593  again: 
3594         len = 0;
3595         len += pack_devicemode(info->devmode, buf+len, buflen-len);
3596
3597         len += pack_values( &info->data, buf+len, buflen-len );
3598
3599         if (buflen != len) {
3600                 char *tb;
3601
3602                 tb = (char *)Realloc(buf, len);
3603                 if (!tb) {
3604                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3605                         ret = -1;
3606                         goto done;
3607                 }
3608                 else
3609                         buf = tb;
3610                 buflen = len;
3611                 goto again;
3612         }
3613
3614         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3615
3616         kbuf.dptr = key;
3617         kbuf.dsize = strlen(key)+1;
3618         dbuf.dptr = buf;
3619         dbuf.dsize = len;
3620
3621         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3622
3623 done:
3624         if (ret == -1)
3625                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3626
3627         SAFE_FREE(buf);
3628
3629         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3630                  info->sharename, info->drivername));
3631
3632         return ret;
3633 }
3634
3635 /****************************************************************************
3636  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3637 ****************************************************************************/
3638
3639 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3640 {
3641         uint32 result;
3642         
3643         dump_a_printer(printer, level); 
3644         
3645         switch (level) {
3646                 case 2:
3647                         result = update_driver_init_2(printer.info_2);
3648                         break;
3649                 default:
3650                         result = 1;
3651                         break;
3652         }
3653         
3654         return result;
3655 }
3656
3657 /****************************************************************************
3658  Convert the printer data value, a REG_BINARY array, into an initialization 
3659  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3660  got to keep the endians happy :).
3661 ****************************************************************************/
3662
3663 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3664 {
3665         BOOL       result = False;
3666         prs_struct ps;
3667         DEVICEMODE devmode;
3668
3669         ZERO_STRUCT(devmode);
3670
3671         prs_init(&ps, 0, ctx, UNMARSHALL);
3672         ps.data_p      = (char *)data;
3673         ps.buffer_size = data_len;
3674
3675         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3676                 result = convert_devicemode("", &devmode, &nt_devmode);
3677         else
3678                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3679
3680         return result;
3681 }
3682
3683 /****************************************************************************
3684  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3685
3686  1. Use the driver's config DLL to this UNC printername and:
3687     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3688     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3689  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3690
3691  The last step triggers saving the "driver initialization" information for
3692  this printer into the tdb. Later, new printers that use this driver will
3693  have this initialization information bound to them. This simulates the
3694  driver initialization, as if it had run on the Samba server (as it would
3695  have done on NT).
3696
3697  The Win32 client side code requirement sucks! But until we can run arbitrary
3698  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3699  
3700  It would have been easier to use SetPrinter because all the UNMARSHALLING of
3701  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3702  about it and you will realize why.  JRR 010720
3703 ****************************************************************************/
3704
3705 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3706 {
3707         WERROR        status       = WERR_OK;
3708         TALLOC_CTX    *ctx         = NULL;
3709         NT_DEVICEMODE *nt_devmode  = NULL;
3710         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3711         
3712         /*
3713          * When the DEVMODE is already set on the printer, don't try to unpack it.
3714          */
3715         DEBUG(8,("save_driver_init_2: Enter...\n"));
3716         
3717         if ( !printer->info_2->devmode && data_len ) {
3718                 /*
3719                  * Set devmode on printer info, so entire printer initialization can be
3720                  * saved to tdb.
3721                  */
3722
3723                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3724                         return WERR_NOMEM;
3725
3726                 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3727                         status = WERR_NOMEM;
3728                         goto done;
3729                 }
3730         
3731                 ZERO_STRUCTP(nt_devmode);
3732
3733                 /*
3734                  * The DEVMODE is held in the 'data' component of the param in raw binary.
3735                  * Convert it to to a devmode structure
3736                  */
3737                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3738                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3739                         status = WERR_INVALID_PARAM;
3740                         goto done;
3741                 }
3742
3743                 printer->info_2->devmode = nt_devmode;
3744         }
3745
3746         /*
3747          * Pack up and add (or update) the DEVMODE and any current printer data to
3748          * a 'driver init' element in the tdb
3749          * 
3750          */
3751
3752         if ( update_driver_init(*printer, 2) != 0 ) {
3753                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3754                 status = WERR_NOMEM;
3755                 goto done;
3756         }
3757         
3758         /*
3759          * If driver initialization info was successfully saved, set the current 
3760          * printer to match it. This allows initialization of the current printer 
3761          * as well as the driver.
3762          */
3763         status = mod_a_printer(*printer, 2);
3764         if (!W_ERROR_IS_OK(status)) {
3765                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3766                                   printer->info_2->printername));
3767         }
3768         
3769   done:
3770         talloc_destroy(ctx);
3771         free_nt_devicemode( &nt_devmode );
3772         
3773         printer->info_2->devmode = tmp_devmode;
3774
3775         return status;
3776 }
3777
3778 /****************************************************************************
3779  Update the driver init info (DEVMODE and specifics) for a printer
3780 ****************************************************************************/
3781
3782 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3783 {
3784         WERROR status = WERR_OK;
3785         
3786         switch (level) {
3787                 case 2:
3788                         status = save_driver_init_2( printer, data, data_len );
3789                         break;
3790                 default:
3791                         status = WERR_UNKNOWN_LEVEL;
3792                         break;
3793         }
3794         
3795         return status;
3796 }
3797
3798 /****************************************************************************
3799  Deep copy a NT_PRINTER_DATA
3800 ****************************************************************************/
3801
3802 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3803 {
3804         int i, j, num_vals, new_key_index;
3805         REGVAL_CTR *src_key, *dst_key;
3806         
3807         if ( !dst || !src )
3808                 return NT_STATUS_NO_MEMORY;
3809         
3810         for ( i=0; i<src->num_keys; i++ ) {
3811                            
3812                 /* create a new instance of the printerkey in the destination 
3813                    printer_data object */
3814                    
3815                 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3816                 dst_key = &dst->keys[new_key_index].values;
3817
3818                 src_key = &src->keys[i].values;
3819                 num_vals = regval_ctr_numvals( src_key );
3820                 
3821                 /* dup the printer entire printer key */
3822                 
3823                 for ( j=0; j<num_vals; j++ ) {
3824                         regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3825                 }
3826         }
3827                 
3828         return NT_STATUS_OK;
3829 }
3830
3831 /****************************************************************************
3832  Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3833  Caller must free.
3834 ****************************************************************************/
3835
3836 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3837 {
3838         NT_PRINTER_INFO_LEVEL_2 *copy;
3839         
3840         if ( !printer )
3841                 return NULL;
3842         
3843         if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3844                 return NULL;
3845                 
3846         memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3847         
3848         /* malloc()'d members copied here */
3849         
3850         copy->devmode = dup_nt_devicemode( printer->devmode );  
3851
3852         ZERO_STRUCT( copy->data );
3853         copy_printer_data( &copy->data, &printer->data );
3854         
3855         /* this is talloc()'d; very ugly that we have a structure that 
3856            is half malloc()'d and half talloc()'d but that is the way 
3857            that the PRINTER_INFO stuff is written right now.  --jerry  */
3858            
3859         copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3860                 
3861         return copy;
3862 }
3863
3864 /****************************************************************************
3865  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3866 ****************************************************************************/
3867
3868 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
3869                         const char *sharename)
3870 {
3871         WERROR result;
3872         NT_PRINTER_INFO_LEVEL *printer = NULL;
3873         
3874         *pp_printer = NULL;
3875
3876         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3877
3878         switch (level) {
3879                 case 2:
3880                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3881                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
3882                                 return WERR_NOMEM;
3883                         }
3884                         ZERO_STRUCTP(printer);
3885                         
3886                         /* 
3887                          * check for cache first.  A Printer handle cannot changed
3888                          * to another printer object so we only check that the printer 
3889                          * is actually for a printer and that the printer_info pointer 
3890                          * is valid
3891                          */
3892                         if ( print_hnd 
3893                                 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER) 
3894                                 && print_hnd->printer_info )
3895                         {
3896                                 if ( !(printer->info_2 = dup_printer_2(print_hnd->ctx, print_hnd->printer_info->info_2)) ) {
3897                                         DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3898                                         
3899                                         SAFE_FREE(printer);
3900                                         return WERR_NOMEM;
3901                                 }
3902                                 
3903                                 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3904                                 
3905                                 *pp_printer = printer;                          
3906                                 result = WERR_OK;
3907                                 
3908                                 break;
3909                         }
3910
3911                         /* no cache for this handle; see if we can match one from another handle */
3912                         
3913                         if ( print_hnd )
3914                                 result = find_printer_in_print_hnd_cache(print_hnd->ctx, &printer->info_2, sharename);
3915                         
3916                         /* fail to disk if we don't have it with any open handle */
3917
3918                         if ( !print_hnd || !W_ERROR_IS_OK(result) )
3919                                 result = get_a_printer_2(&printer->info_2, sharename);                          
3920                         
3921                         /* we have a new printer now.  Save it with this handle */
3922                         
3923                         if ( W_ERROR_IS_OK(result) ) {
3924                                 dump_a_printer(*printer, level);
3925                                         
3926                                 /* save a copy in cache */
3927                                 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
3928                                         if ( !print_hnd->printer_info )
3929                                                 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
3930
3931                                         if ( print_hnd->printer_info ) {
3932                                                 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
3933                                                 
3934                                                 /* don't fail the lookup just because the cache update failed */
3935                                                 if ( !print_hnd->printer_info->info_2 )
3936                                                         DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
3937                                         }
3938                                 }
3939                                 *pp_printer = printer;  
3940                         }
3941                         else
3942                                 SAFE_FREE(printer);
3943                         
3944                         break;
3945                         
3946                 default:
3947                         result=WERR_UNKNOWN_LEVEL;
3948                         break;
3949         }
3950         
3951         DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3952
3953         return result;
3954 }
3955
3956 /****************************************************************************
3957  Deletes a NT_PRINTER_INFO_LEVEL struct.
3958 ****************************************************************************/
3959
3960 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3961 {
3962         uint32 result;
3963         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3964
3965         DEBUG(104,("freeing a printer at level [%d]\n", level));
3966
3967         if (printer == NULL)
3968                 return 0;
3969         
3970         switch (level) {
3971                 case 2:
3972                         if (printer->info_2 != NULL) {
3973                                 free_nt_printer_info_level_2(&printer->info_2);
3974                                 result=0;
3975                         } else
3976                                 result=4;
3977                         break;
3978
3979                 default:
3980                         result=1;
3981                         break;
3982         }
3983
3984         SAFE_FREE(*pp_printer);
3985         return result;
3986 }
3987
3988 /****************************************************************************
3989 ****************************************************************************/
3990 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3991 {
3992         uint32 result;
3993         DEBUG(104,("adding a printer at level [%d]\n", level));
3994         dump_a_printer_driver(driver, level);
3995         
3996         switch (level) {
3997                 case 3:
3998                         result=add_a_printer_driver_3(driver.info_3);
3999                         break;
4000
4001                 case 6:
4002                         result=add_a_printer_driver_6(driver.info_6);
4003                         break;
4004
4005                 default:
4006                         result=1;
4007                         break;
4008         }
4009         
4010         return result;
4011 }
4012 /****************************************************************************
4013 ****************************************************************************/
4014
4015 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4016                             fstring drivername, const char *architecture, uint32 version)
4017 {
4018         WERROR result;
4019         
4020         switch (level) {
4021                 case 3:
4022                         /* Sometime we just want any version of the driver */
4023                         
4024                         if ( version == DRIVER_ANY_VERSION ) {
4025                                 /* look for Win2k first and then for NT4 */
4026                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4027                                                 architecture, 3);
4028                                                 
4029                                 if ( !W_ERROR_IS_OK(result) ) {
4030                                         result = get_a_printer_driver_3( &driver->info_3, 
4031                                                         drivername, architecture, 2 );
4032                                 }
4033                         } else {
4034                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4035                                         architecture, version);                         
4036                         }
4037                         break;
4038                         
4039                 default:
4040                         result=W_ERROR(1);
4041                         break;
4042         }
4043         
4044         if (W_ERROR_IS_OK(result))
4045                 dump_a_printer_driver(*driver, level);
4046                 
4047         return result;
4048 }
4049
4050 /****************************************************************************
4051 ****************************************************************************/
4052 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4053 {
4054         uint32 result;
4055         
4056         switch (level) {
4057                 case 3:
4058                 {
4059                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4060                         if (driver.info_3 != NULL)
4061                         {
4062                                 info3=driver.info_3;
4063                                 SAFE_FREE(info3->dependentfiles);
4064                                 ZERO_STRUCTP(info3);
4065                                 SAFE_FREE(info3);
4066                                 result=0;
4067                         } else {
4068                                 result=4;
4069                         }
4070                         break;
4071                 }
4072                 case 6:
4073                 {
4074                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4075                         if (driver.info_6 != NULL) {
4076                                 info6=driver.info_6;
4077                                 SAFE_FREE(info6->dependentfiles);
4078                                 SAFE_FREE(info6->previousnames);
4079                                 ZERO_STRUCTP(info6);
4080                                 SAFE_FREE(info6);
4081                                 result=0;
4082                         } else {
4083                                 result=4;
4084                         }
4085                         break;
4086                 }
4087                 default:
4088                         result=1;
4089                         break;
4090         }
4091         return result;
4092 }
4093
4094
4095 /****************************************************************************
4096   Determine whether or not a particular driver is currently assigned
4097   to a printer
4098 ****************************************************************************/
4099
4100 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4101 {
4102         int snum;
4103         int n_services = lp_numservices();
4104         NT_PRINTER_INFO_LEVEL *printer = NULL;
4105
4106         if ( !info_3 ) 
4107                 return False;
4108
4109         DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4110         
4111         /* loop through the printers.tdb and check for the drivername */
4112         
4113         for (snum=0; snum<n_services; snum++) {
4114                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4115                         continue;
4116                 
4117                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4118                         continue;
4119                 
4120                 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4121                         free_a_printer( &printer, 2 );
4122                         return True;
4123                 }
4124                 
4125                 free_a_printer( &printer, 2 );
4126         }
4127         
4128         DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4129         
4130         /* report that the driver is not in use by default */
4131         
4132         return False;
4133 }
4134
4135
4136 /**********************************************************************
4137  Check to see if a ogiven file is in use by *info
4138  *********************************************************************/
4139  
4140 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4141 {
4142         int i = 0;
4143         
4144         if ( !info )
4145                 return False;
4146                 
4147         if ( strequal(file, info->driverpath) )
4148                 return True;
4149
4150         if ( strequal(file, info->datafile) )
4151                 return True;
4152
4153         if ( strequal(file, info->configfile) )
4154                 return True;
4155
4156         if ( strequal(file, info->helpfile) )
4157                 return True;
4158         
4159         /* see of there are any dependent files to examine */
4160         
4161         if ( !info->dependentfiles )
4162                 return False;
4163         
4164         while ( *info->dependentfiles[i] ) {
4165                 if ( strequal(file, info->dependentfiles[i]) )
4166                         return True;
4167                 i++;
4168         }
4169         
4170         return False;
4171
4172 }
4173
4174 /**********************************************************************
4175  Utility function to remove the dependent file pointed to by the 
4176  input parameter from the list 
4177  *********************************************************************/
4178
4179 static void trim_dependent_file( fstring files[], int idx )
4180 {
4181         
4182         /* bump everything down a slot */
4183
4184         while( *files[idx+1] ) {
4185                 fstrcpy( files[idx], files[idx+1] );
4186                 idx++;
4187         }
4188         
4189         *files[idx] = '\0';
4190
4191         return; 
4192 }
4193
4194 /**********************************************************************
4195  Check if any of the files used by src are also used by drv 
4196  *********************************************************************/
4197
4198 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4199                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4200 {
4201         BOOL    in_use = False;
4202         int     i = 0;
4203         
4204         if ( !src || !drv )
4205                 return False;
4206                 
4207         /* check each file.  Remove it from the src structure if it overlaps */
4208         
4209         if ( drv_file_in_use(src->driverpath, drv) ) {
4210                 in_use = True;
4211                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4212                 fstrcpy( src->driverpath, "" );
4213         }
4214                 
4215         if ( drv_file_in_use(src->datafile, drv) ) {
4216                 in_use = True;
4217                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4218                 fstrcpy( src->datafile, "" );
4219         }
4220                 
4221         if ( drv_file_in_use(src->configfile, drv) ) {
4222                 in_use = True;
4223                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4224                 fstrcpy( src->configfile, "" );
4225         }
4226                 
4227         if ( drv_file_in_use(src->helpfile, drv) ) {
4228                 in_use = True;
4229                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4230                 fstrcpy( src->helpfile, "" );
4231         }
4232         
4233         /* are there any dependentfiles to examine? */
4234         
4235         if ( !src->dependentfiles )
4236                 return in_use;
4237                 
4238         while ( *src->dependentfiles[i] ) {
4239                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4240                         in_use = True;
4241                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4242                         trim_dependent_file( src->dependentfiles, i );
4243                 } else
4244                         i++;
4245         }               
4246                 
4247         return in_use;
4248 }
4249
4250 /****************************************************************************
4251   Determine whether or not a particular driver files are currently being 
4252   used by any other driver.  
4253   
4254   Return value is True if any files were in use by other drivers
4255   and False otherwise.
4256   
4257   Upon return, *info has been modified to only contain the driver files
4258   which are not in use
4259 ****************************************************************************/
4260
4261 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4262 {
4263         int                             i;
4264         int                             ndrivers;
4265         uint32                          version;
4266         fstring                         *list = NULL;
4267         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4268         
4269         if ( !info )
4270                 return False;
4271         
4272         version = info->cversion;
4273         
4274         /* loop over all driver versions */
4275         
4276         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4277         
4278         /* get the list of drivers */
4279                 
4280         list = NULL;
4281         ndrivers = get_ntdrivers(&list, info->environment, version);
4282                 
4283         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4284                 ndrivers, info->environment, version));
4285
4286         /* check each driver for overlap in files */
4287                 
4288         for (i=0; i<ndrivers; i++) {
4289                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4290                         
4291                 ZERO_STRUCT(driver);
4292                         
4293                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4294                         SAFE_FREE(list);
4295                         return True;
4296                 }
4297                         
4298                 /* check if d2 uses any files from d1 */
4299                 /* only if this is a different driver than the one being deleted */
4300                         
4301                 if ( !strequal(info->name, driver.info_3->name) ) {
4302                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4303                                 free_a_printer_driver(driver, 3);
4304                                 SAFE_FREE( list );
4305                                 return True;
4306                         }
4307                 }
4308         
4309                 free_a_printer_driver(driver, 3);
4310         }       
4311         
4312         SAFE_FREE(list);
4313         
4314         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4315         
4316         driver.info_3 = info;
4317         
4318         if ( DEBUGLEVEL >= 20 )
4319                 dump_a_printer_driver( driver, 3 );
4320         
4321         return False;
4322 }
4323
4324 /****************************************************************************
4325   Actually delete the driver files.  Make sure that 
4326   printer_driver_files_in_use() return False before calling 
4327   this.
4328 ****************************************************************************/
4329
4330 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4331 {
4332         int i = 0;
4333         char *s;
4334         connection_struct *conn;
4335         DATA_BLOB null_pw;
4336         NTSTATUS nt_status;
4337         fstring res_type;
4338
4339         if ( !info_3 )
4340                 return False;
4341                 
4342         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4343         
4344         /*
4345          * Connect to the print$ share under the same account as the 
4346          * user connected to the rpc pipe. Note we must be root to 
4347          * do this.
4348          */
4349          
4350         null_pw = data_blob( NULL, 0 );
4351         fstrcpy(res_type, "A:");
4352         become_root();
4353         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4354         unbecome_root();
4355         
4356         if ( !conn ) {
4357                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4358                 return False;
4359         }
4360
4361         /* Save who we are - we are temporarily becoming the connection user. */
4362
4363         if ( !become_user(conn, conn->vuid) ) {
4364                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4365                 return False;
4366         }
4367
4368         /* now delete the files; must strip the '\print$' string from 
4369            fron of path                                                */
4370         
4371         if ( *info_3->driverpath ) {
4372                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4373                         DEBUG(10,("deleting driverfile [%s]\n", s));
4374                         unlink_internals(conn, 0, s);
4375                 }
4376         }
4377                 
4378         if ( *info_3->configfile ) {
4379                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4380                         DEBUG(10,("deleting configfile [%s]\n", s));
4381                         unlink_internals(conn, 0, s);
4382                 }
4383         }
4384         
4385         if ( *info_3->datafile ) {
4386                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4387                         DEBUG(10,("deleting datafile [%s]\n", s));
4388                         unlink_internals(conn, 0, s);
4389                 }
4390         }
4391         
4392         if ( *info_3->helpfile ) {
4393                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4394                         DEBUG(10,("deleting helpfile [%s]\n", s));
4395                         unlink_internals(conn, 0, s);
4396                 }
4397         }
4398         
4399         /* check if we are done removing files */
4400         
4401         if ( info_3->dependentfiles ) {
4402                 while ( *info_3->dependentfiles[i] ) {
4403                         char *file;
4404
4405                         /* bypass the "\print$" portion of the path */
4406                         
4407                         if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4408                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4409                                 unlink_internals(conn, 0, file );
4410                         }
4411                         
4412                         i++;
4413                 }
4414         }
4415
4416         unbecome_user();
4417         
4418         return True;
4419 }
4420
4421 /****************************************************************************
4422  Remove a printer driver from the TDB.  This assumes that the the driver was
4423  previously looked up.
4424  ***************************************************************************/
4425
4426 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4427                               uint32 version, BOOL delete_files )
4428 {
4429         pstring         key;
4430         const char     *arch;
4431         TDB_DATA        kbuf, dbuf;
4432         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4433
4434         /* delete the tdb data first */
4435
4436         arch = get_short_archi(info_3->environment);
4437         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4438                 arch, version, info_3->name);
4439
4440         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4441                 key, delete_files ? "TRUE" : "FALSE" ));
4442
4443         ctr.info_3 = info_3;
4444         dump_a_printer_driver( ctr, 3 );
4445
4446         kbuf.dptr=key;
4447         kbuf.dsize=strlen(key)+1;
4448
4449         /* check if the driver actually exists for this environment */
4450         
4451         dbuf = tdb_fetch( tdb_drivers, kbuf );
4452         if ( !dbuf.dptr ) {
4453                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4454                 return WERR_UNKNOWN_PRINTER_DRIVER;
4455         }
4456                 
4457         SAFE_FREE( dbuf.dptr );
4458         
4459         /* ok... the driver exists so the delete should return success */
4460                 
4461         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4462                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4463                 return WERR_ACCESS_DENIED;
4464         }
4465
4466         /*
4467          * now delete any associated files if delete_files == True
4468          * even if this part failes, we return succes because the
4469          * driver doesn not exist any more
4470          */
4471
4472         if ( delete_files )
4473                 delete_driver_files( info_3, user );
4474                         
4475                 
4476         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4477
4478         return WERR_OK;
4479         }
4480         
4481 /****************************************************************************
4482  Store a security desc for a printer.
4483 ****************************************************************************/
4484
4485 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4486 {
4487         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4488         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4489         prs_struct ps;
4490         TALLOC_CTX *mem_ctx = NULL;
4491         fstring key;
4492         WERROR status;
4493
4494         mem_ctx = talloc_init("nt_printing_setsec");
4495         if (mem_ctx == NULL)
4496                 return WERR_NOMEM;
4497
4498         /* The old owner and group sids of the security descriptor are not
4499            present when new ACEs are added or removed by changing printer
4500            permissions through NT.  If they are NULL in the new security
4501            descriptor then copy them over from the old one. */
4502
4503         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4504                 DOM_SID *owner_sid, *group_sid;
4505                 SEC_ACL *dacl, *sacl;
4506                 SEC_DESC *psd = NULL;
4507                 size_t size;
4508
4509                 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4510
4511                 /* Pick out correct owner and group sids */
4512
4513                 owner_sid = secdesc_ctr->sec->owner_sid ?
4514                         secdesc_ctr->sec->owner_sid :
4515                         old_secdesc_ctr->sec->owner_sid;
4516
4517                 group_sid = secdesc_ctr->sec->grp_sid ?
4518                         secdesc_ctr->sec->grp_sid :
4519                         old_secdesc_ctr->sec->grp_sid;
4520
4521                 dacl = secdesc_ctr->sec->dacl ?
4522                         secdesc_ctr->sec->dacl :
4523                         old_secdesc_ctr->sec->dacl;
4524
4525                 sacl = secdesc_ctr->sec->sacl ?
4526                         secdesc_ctr->sec->sacl :
4527                         old_secdesc_ctr->sec->sacl;
4528
4529                 /* Make a deep copy of the security descriptor */
4530
4531                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
4532                                     owner_sid, group_sid,
4533                                     sacl,
4534                                     dacl,
4535                                     &size);
4536
4537                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4538         }
4539
4540         if (!new_secdesc_ctr) {
4541                 new_secdesc_ctr = secdesc_ctr;
4542         }
4543
4544         /* Store the security descriptor in a tdb */
4545
4546         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4547                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4548
4549         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4550                              &ps, 1)) {
4551                 status = WERR_BADFUNC;
4552                 goto out;
4553         }
4554
4555         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4556
4557         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4558                 status = WERR_OK;
4559         } else {
4560                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4561                 status = WERR_BADFUNC;
4562         }
4563
4564         /* Free malloc'ed memory */
4565
4566  out:
4567
4568         prs_mem_free(&ps);
4569         if (mem_ctx)
4570                 talloc_destroy(mem_ctx);
4571         return status;
4572 }
4573
4574 /****************************************************************************
4575  Construct a default security descriptor buffer for a printer.
4576 ****************************************************************************/
4577
4578 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4579 {
4580         SEC_ACE ace[3];
4581         SEC_ACCESS sa;
4582         SEC_ACL *psa = NULL;
4583         SEC_DESC_BUF *sdb = NULL;
4584         SEC_DESC *psd = NULL;
4585         DOM_SID owner_sid;
4586         size_t sd_size;
4587
4588         /* Create an ACE where Everyone is allowed to print */
4589
4590         init_sec_access(&sa, PRINTER_ACE_PRINT);
4591         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4592                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4593
4594         /* Make the security descriptor owned by the Administrators group
4595            on the PDC of the domain. */
4596
4597         if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4598                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4599         } else {
4600
4601                 /* Backup plan - make printer owned by admins.
4602                    This should emulate a lanman printer as security
4603                    settings can't be changed. */
4604
4605                 sid_copy(&owner_sid, get_global_sam_sid());
4606                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4607         }
4608
4609         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4610         init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4611                      sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4612                      SEC_ACE_FLAG_INHERIT_ONLY);
4613
4614         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4615         init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4616                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4617
4618         /* The ACL revision number in rpc_secdesc.h differs from the one
4619            created by NT when setting ACE entries in printer
4620            descriptors.  NT4 complains about the property being edited by a
4621            NT5 machine. */
4622
4623         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4624                 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4625                                     &owner_sid, NULL,
4626                                     NULL, psa, &sd_size);
4627         }
4628
4629         if (!psd) {
4630                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4631                 return NULL;
4632         }
4633
4634         sdb = make_sec_desc_buf(ctx, sd_size, psd);
4635
4636         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4637                  (unsigned int)sd_size));
4638
4639         return sdb;
4640 }
4641
4642 /****************************************************************************
4643  Get a security desc for a printer.
4644 ****************************************************************************/
4645
4646 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4647 {
4648         prs_struct ps;
4649         fstring key;
4650         char *temp;
4651
4652         if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4653                 printername = temp + 1;
4654         }
4655
4656         /* Fetch security descriptor from tdb */
4657
4658         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4659
4660         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4661             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4662
4663                 DEBUG(4,("using default secdesc for %s\n", printername));
4664
4665                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4666                         return False;
4667                 }
4668
4669                 /* Save default security descriptor for later */
4670
4671                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4672                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4673
4674                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4675                         tdb_prs_store(tdb_printers, key, &ps);
4676
4677                 prs_mem_free(&ps);
4678
4679                 return True;
4680         }
4681
4682         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4683            this security descriptor has been created when winbindd was
4684            down.  Take ownership of security descriptor. */
4685
4686         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4687                 DOM_SID owner_sid;
4688
4689                 /* Change sd owner to workgroup administrator */
4690
4691                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4692                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4693                         SEC_DESC *psd = NULL;
4694                         size_t size;
4695
4696                         /* Create new sd */
4697
4698                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4699
4700                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4701                                             &owner_sid,
4702                                             (*secdesc_ctr)->sec->grp_sid,
4703                                             (*secdesc_ctr)->sec->sacl,
4704                                             (*secdesc_ctr)->sec->dacl,
4705                                             &size);
4706
4707                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4708
4709                         /* Swap with other one */
4710
4711                         *secdesc_ctr = new_secdesc_ctr;
4712
4713                         /* Set it */
4714
4715                         nt_printing_setsec(printername, *secdesc_ctr);
4716                 }
4717         }
4718
4719         if (DEBUGLEVEL >= 10) {
4720                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4721                 int i;
4722
4723                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4724                            printername, the_acl->num_aces));
4725
4726                 for (i = 0; i < the_acl->num_aces; i++) {
4727                         fstring sid_str;
4728
4729                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4730
4731                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4732                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
4733                                    the_acl->ace[i].info.mask)); 
4734                 }
4735         }
4736
4737         prs_mem_free(&ps);
4738         return True;
4739 }
4740
4741 /* error code:
4742         0: everything OK
4743         1: level not implemented
4744         2: file doesn't exist
4745         3: can't allocate memory
4746         4: can't free memory
4747         5: non existant struct
4748 */
4749
4750 /*
4751         A printer and a printer driver are 2 different things.
4752         NT manages them separatelly, Samba does the same.
4753         Why ? Simply because it's easier and it makes sense !
4754         
4755         Now explanation: You have 3 printers behind your samba server,
4756         2 of them are the same make and model (laser A and B). But laser B
4757         has an 3000 sheet feeder and laser A doesn't such an option.
4758         Your third printer is an old dot-matrix model for the accounting :-).
4759         
4760         If the /usr/local/samba/lib directory (default dir), you will have
4761         5 files to describe all of this.
4762         
4763         3 files for the printers (1 by printer):
4764                 NTprinter_laser A
4765                 NTprinter_laser B
4766                 NTprinter_accounting
4767         2 files for the drivers (1 for the laser and 1 for the dot matrix)
4768                 NTdriver_printer model X
4769                 NTdriver_printer model Y
4770
4771 jfm: I should use this comment for the text file to explain
4772         same thing for the forms BTW.
4773         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4774
4775 */
4776
4777 /* Convert generic access rights to printer object specific access rights.
4778    It turns out that NT4 security descriptors use generic access rights and
4779    NT5 the object specific ones. */
4780
4781 void map_printer_permissions(SEC_DESC *sd)
4782 {
4783         int i;
4784
4785         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4786                 se_map_generic(&sd->dacl->ace[i].info.mask,
4787                                &printer_generic_mapping);
4788         }
4789 }
4790
4791 /****************************************************************************
4792  Check a user has permissions to perform the given operation.  We use the
4793  permission constants defined in include/rpc_spoolss.h to check the various
4794  actions we perform when checking printer access.
4795
4796    PRINTER_ACCESS_ADMINISTER:
4797        print_queue_pause, print_queue_resume, update_printer_sec,
4798        update_printer, spoolss_addprinterex_level_2,
4799        _spoolss_setprinterdata
4800
4801    PRINTER_ACCESS_USE:
4802        print_job_start
4803
4804    JOB_ACCESS_ADMINISTER:
4805        print_job_delete, print_job_pause, print_job_resume,
4806        print_queue_purge
4807
4808  ****************************************************************************/
4809 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4810 {
4811         SEC_DESC_BUF *secdesc = NULL;
4812         uint32 access_granted;
4813         NTSTATUS status;
4814         BOOL result;
4815         const char *pname;
4816         TALLOC_CTX *mem_ctx = NULL;
4817         extern struct current_user current_user;
4818         
4819         /* If user is NULL then use the current_user structure */
4820
4821         if (!user)
4822                 user = &current_user;
4823
4824         /* Always allow root or printer admins to do anything */
4825
4826         if (user->uid == 0 ||
4827             user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4828                 return True;
4829         }
4830
4831         /* Get printer name */
4832
4833         pname = PRINTERNAME(snum);
4834
4835         if (!pname || !*pname) {
4836                 errno = EACCES;
4837                 return False;
4838         }
4839
4840         /* Get printer security descriptor */
4841
4842         if(!(mem_ctx = talloc_init("print_access_check"))) {
4843                 errno = ENOMEM;
4844                 return False;
4845         }
4846
4847         nt_printing_getsec(mem_ctx, pname, &secdesc);
4848
4849         if (access_type == JOB_ACCESS_ADMINISTER) {
4850                 SEC_DESC_BUF *parent_secdesc = secdesc;
4851
4852                 /* Create a child security descriptor to check permissions
4853                    against.  This is because print jobs are child objects
4854                    objects of a printer. */
4855
4856                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4857
4858                 /* Now this is the bit that really confuses me.  The access
4859                    type needs to be changed from JOB_ACCESS_ADMINISTER to
4860                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
4861                    to do with the child (job) object becoming like a
4862                    printer??  -tpot */
4863
4864                 access_type = PRINTER_ACCESS_ADMINISTER;
4865         }
4866         
4867         /* Check access */
4868         
4869         map_printer_permissions(secdesc->sec);
4870
4871         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4872                                  &access_granted, &status);
4873
4874         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4875
4876         talloc_destroy(mem_ctx);
4877         
4878         if (!result)
4879                 errno = EACCES;
4880
4881         return result;
4882 }
4883
4884 /****************************************************************************
4885  Check the time parameters allow a print operation.
4886 *****************************************************************************/
4887
4888 BOOL print_time_access_check(int snum)
4889 {
4890         NT_PRINTER_INFO_LEVEL *printer = NULL;
4891         BOOL ok = False;
4892         time_t now = time(NULL);
4893         struct tm *t;
4894         uint32 mins;
4895
4896         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
4897                 return False;
4898
4899         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4900                 ok = True;
4901
4902         t = gmtime(&now);
4903         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4904
4905         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4906                 ok = True;
4907
4908         free_a_printer(&printer, 2);
4909
4910         if (!ok)
4911                 errno = EACCES;
4912
4913         return ok;
4914 }
4915