sync 3.0 into HEAD for the last time
[samba.git] / source3 / 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( architecture, 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_char(info->printername, '\\', '\0');
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         /* make sure the value exists so we can return the correct error code */
2902         
2903         if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
2904                 return WERR_BADFILE;
2905                 
2906         regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2907         
2908         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2909                 key, value ));
2910         
2911         return result;
2912 }
2913
2914 /****************************************************************************
2915  ***************************************************************************/
2916  
2917 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
2918                            uint32 type, uint8 *data, int real_len )
2919 {
2920         WERROR          result = WERR_OK;
2921         int             key_index;
2922
2923         /* we must have names on non-zero length */
2924         
2925         if ( !key || !*key|| !value || !*value )
2926                 return WERR_INVALID_NAME;
2927                 
2928         /* find the printer key first */
2929         
2930         key_index = lookup_printerkey( &p2->data, key );
2931         if ( key_index == -1 )
2932                 key_index = add_new_printer_key( &p2->data, key );
2933                 
2934         if ( key_index == -1 )
2935                 return WERR_NOMEM;
2936         
2937         regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2938                 type, (const char *)data, real_len );
2939         
2940         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2941                 key, value, type, real_len  ));
2942         
2943         return result;
2944 }
2945
2946 /****************************************************************************
2947  ***************************************************************************/
2948  
2949 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2950 {
2951         int             key_index;
2952
2953         if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2954                 return NULL;
2955
2956         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2957                 key, value ));
2958
2959         return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
2960 }
2961
2962 /****************************************************************************
2963  Unpack a list of registry values frem the TDB
2964  ***************************************************************************/
2965  
2966 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
2967 {
2968         int             len = 0;
2969         uint32          type;
2970         pstring         string, valuename, keyname;
2971         char            *str;
2972         int             size;
2973         uint8           *data_p;
2974         REGISTRY_VALUE  *regval_p;
2975         int             key_index;
2976         
2977         /* add the "PrinterDriverData" key first for performance reasons */
2978         
2979         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
2980
2981         /* loop and unpack the rest of the registry values */
2982         
2983         while ( True ) {
2984         
2985                 /* check to see if there are any more registry values */
2986                 
2987                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
2988                 if ( !regval_p ) 
2989                         break;
2990
2991                 /* unpack the next regval */
2992                 
2993                 len += tdb_unpack(buf+len, buflen-len, "fdB",
2994                                   string,
2995                                   &type,
2996                                   &size,
2997                                   &data_p);
2998         
2999                 /*
3000                  * break of the keyname from the value name.  
3001                  * Should only be one '\' in the string returned.
3002                  */     
3003                  
3004                 str = strrchr( string, '\\');
3005                 
3006                 /* Put in "PrinterDriverData" is no key specified */
3007                 
3008                 if ( !str ) {
3009                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3010                         pstrcpy( valuename, string );
3011                 }
3012                 else {
3013                         *str = '\0';
3014                         pstrcpy( keyname, string );
3015                         pstrcpy( valuename, str+1 );
3016                 }
3017                         
3018                 /* see if we need a new key */
3019                 
3020                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3021                         key_index = add_new_printer_key( printer_data, keyname );
3022                         
3023                 if ( key_index == -1 ) {
3024                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3025                                 keyname));
3026                         break;
3027                 }
3028                 
3029                 /* add the new value */
3030                 
3031                 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3032
3033                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3034
3035                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3036         }
3037
3038         return len;
3039 }
3040
3041 /****************************************************************************
3042  ***************************************************************************/
3043
3044 static void map_to_os2_driver(fstring drivername)
3045 {
3046         static BOOL initialised=False;
3047         static fstring last_from,last_to;
3048         char *mapfile = lp_os2_driver_map();
3049         char **lines = NULL;
3050         int numlines = 0;
3051         int i;
3052
3053         if (!strlen(drivername))
3054                 return;
3055
3056         if (!*mapfile)
3057                 return;
3058
3059         if (!initialised) {
3060                 *last_from = *last_to = 0;
3061                 initialised = True;
3062         }
3063
3064         if (strequal(drivername,last_from)) {
3065                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3066                 fstrcpy(drivername,last_to);
3067                 return;
3068         }
3069
3070         lines = file_lines_load(mapfile, &numlines);
3071         if (numlines == 0) {
3072                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3073                 return;
3074         }
3075
3076         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3077
3078         for( i = 0; i < numlines; i++) {
3079                 char *nt_name = lines[i];
3080                 char *os2_name = strchr(nt_name,'=');
3081
3082                 if (!os2_name)
3083                         continue;
3084
3085                 *os2_name++ = 0;
3086
3087                 while (isspace(*nt_name))
3088                         nt_name++;
3089
3090                 if (!*nt_name || strchr("#;",*nt_name))
3091                         continue;
3092
3093                 {
3094                         int l = strlen(nt_name);
3095                         while (l && isspace(nt_name[l-1])) {
3096                                 nt_name[l-1] = 0;
3097                                 l--;
3098                         }
3099                 }
3100
3101                 while (isspace(*os2_name))
3102                         os2_name++;
3103
3104                 {
3105                         int l = strlen(os2_name);
3106                         while (l && isspace(os2_name[l-1])) {
3107                                 os2_name[l-1] = 0;
3108                                 l--;
3109                         }
3110                 }
3111
3112                 if (strequal(nt_name,drivername)) {
3113                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3114                         fstrcpy(last_from,drivername);
3115                         fstrcpy(last_to,os2_name);
3116                         fstrcpy(drivername,os2_name);
3117                         file_lines_free(lines);
3118                         return;
3119                 }
3120         }
3121
3122         file_lines_free(lines);
3123 }
3124
3125 /****************************************************************************
3126  Get a default printer info 2 struct.
3127 ****************************************************************************/
3128 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3129 {
3130         int snum;
3131         NT_PRINTER_INFO_LEVEL_2 info;
3132
3133         ZERO_STRUCT(info);
3134
3135         snum = lp_servicenumber(sharename);
3136
3137         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3138         slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
3139                  get_called_name(), sharename);
3140         fstrcpy(info.sharename, sharename);
3141         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3142
3143         /* by setting the driver name to an empty string, a local NT admin
3144            can now run the **local** APW to install a local printer driver
3145            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3146            installed on the Samba server for NT clients --jerry */
3147 #if 0   /* JERRY --do not uncomment-- */
3148         if (!*info.drivername)
3149                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3150 #endif
3151
3152
3153         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3154
3155         pstrcpy(info.comment, "");
3156         fstrcpy(info.printprocessor, "winprint");
3157         fstrcpy(info.datatype, "RAW");
3158
3159         info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3160
3161         info.starttime = 0; /* Minutes since 12:00am GMT */
3162         info.untiltime = 0; /* Minutes since 12:00am GMT */
3163         info.priority = 1;
3164         info.default_priority = 1;
3165         info.setuptime = (uint32)time(NULL);
3166
3167         /*
3168          * I changed this as I think it is better to have a generic
3169          * DEVMODE than to crash Win2k explorer.exe   --jerry
3170          * See the HP Deskjet 990c Win2k drivers for an example.
3171          *
3172          * However the default devmode appears to cause problems
3173          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3174          * the "default devmode" parameter   --jerry 22/01/2002
3175          */
3176
3177         if (lp_default_devmode(snum)) {
3178                 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3179                         goto fail;
3180         }
3181         else {
3182                 info.devmode = NULL;
3183         }
3184
3185         /* This will get the current RPC talloc context, but we should be
3186            passing this as a parameter... fixme... JRA ! */
3187
3188         if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3189                 goto fail;
3190
3191         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3192         if (! *info_ptr) {
3193                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3194                 goto fail;
3195         }
3196
3197         return WERR_OK;
3198
3199   fail:
3200         if (info.devmode)
3201                 free_nt_devicemode(&info.devmode);
3202         return WERR_ACCESS_DENIED;
3203 }
3204
3205 /****************************************************************************
3206 ****************************************************************************/
3207 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3208 {
3209         pstring key;
3210         NT_PRINTER_INFO_LEVEL_2 info;
3211         int             len = 0;
3212         TDB_DATA kbuf, dbuf;
3213         fstring printername;
3214         char adevice[MAXDEVICENAME];
3215                 
3216         ZERO_STRUCT(info);
3217
3218         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3219
3220         kbuf.dptr = key;
3221         kbuf.dsize = strlen(key)+1;
3222
3223         dbuf = tdb_fetch(tdb_printers, kbuf);
3224         if (!dbuf.dptr)
3225                 return get_a_printer_2_default(info_ptr, sharename);
3226
3227         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3228                         &info.attributes,
3229                         &info.priority,
3230                         &info.default_priority,
3231                         &info.starttime,
3232                         &info.untiltime,
3233                         &info.status,
3234                         &info.cjobs,
3235                         &info.averageppm,
3236                         &info.changeid,
3237                         &info.c_setprinter,
3238                         &info.setuptime,
3239                         info.servername,
3240                         info.printername,
3241                         info.sharename,
3242                         info.portname,
3243                         info.drivername,
3244                         info.comment,
3245                         info.location,
3246                         info.sepfile,
3247                         info.printprocessor,
3248                         info.datatype,
3249                         info.parameters);
3250
3251         /* Samba has to have shared raw drivers. */
3252         info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3253
3254         /* Restore the stripped strings. */
3255         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3256         slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3257                         info.printername);
3258         fstrcpy(info.printername, printername);
3259
3260         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3261
3262         /*
3263          * Some client drivers freak out if there is a NULL devmode
3264          * (probably the driver is not checking before accessing 
3265          * the devmode pointer)   --jerry
3266          *
3267          * See comments in get_a_printer_2_default()
3268          */
3269
3270         if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3271                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3272                         printername));
3273                 info.devmode = construct_nt_devicemode(printername);
3274         }
3275         
3276         safe_strcpy(adevice, info.printername, sizeof(adevice)-1);
3277         fstrcpy(info.devmode->devicename, adevice);     
3278
3279
3280         len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3281
3282         /* This will get the current RPC talloc context, but we should be
3283            passing this as a parameter... fixme... JRA ! */
3284
3285         nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3286
3287         /* Fix for OS/2 drivers. */
3288
3289         if (get_remote_arch() == RA_OS2)
3290                 map_to_os2_driver(info.drivername);
3291
3292         SAFE_FREE(dbuf.dptr);
3293         *info_ptr=memdup(&info, sizeof(info));
3294
3295         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3296                  sharename, info.printername, info.drivername));
3297
3298         return WERR_OK; 
3299 }
3300
3301 /****************************************************************************
3302  Debugging function, dump at level 6 the struct in the logs.
3303 ****************************************************************************/
3304 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3305 {
3306         uint32 result;
3307         NT_PRINTER_INFO_LEVEL_2 *info2;
3308         
3309         DEBUG(106,("Dumping printer at level [%d]\n", level));
3310         
3311         switch (level) {
3312                 case 2:
3313                 {
3314                         if (printer.info_2 == NULL)
3315                                 result=5;
3316                         else
3317                         {
3318                                 info2=printer.info_2;
3319                         
3320                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3321                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3322                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3323                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3324                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3325                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3326                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3327                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3328                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3329                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3330                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3331
3332                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3333                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3334                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3335                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3336                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3337                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3338                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3339                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3340                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3341                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3342                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3343                                 result=0;
3344                         }
3345                         break;
3346                 }
3347                 default:
3348                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3349                         result=1;
3350                         break;
3351         }
3352         
3353         return result;
3354 }
3355
3356 /****************************************************************************
3357  Update the changeid time.
3358  This is SO NASTY as some drivers need this to change, others need it
3359  static. This value will change every second, and I must hope that this
3360  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3361  UTAH ! JRA.
3362 ****************************************************************************/
3363
3364 static uint32 rev_changeid(void)
3365 {
3366         struct timeval tv;
3367
3368         get_process_uptime(&tv);
3369
3370 #if 1   /* JERRY */
3371         /* Return changeid as msec since spooler restart */
3372         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3373 #else
3374         /*
3375          * This setting seems to work well but is too untested
3376          * to replace the above calculation.  Left in for experiementation
3377          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3378          */
3379         return tv.tv_sec * 10 + tv.tv_usec / 100000;
3380 #endif
3381 }
3382
3383 /*
3384  * The function below are the high level ones.
3385  * only those ones must be called from the spoolss code.
3386  * JFM.
3387  */
3388
3389 /****************************************************************************
3390  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3391 ****************************************************************************/
3392
3393 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3394 {
3395         WERROR result;
3396         
3397         dump_a_printer(printer, level); 
3398         
3399         /* 
3400          * invalidate cache for all open handles to this printer.
3401          * cache for a given handle will be updated on the next 
3402          * get_a_printer() 
3403          */
3404          
3405         invalidate_printer_hnd_cache( printer.info_2->sharename );
3406         
3407         switch (level) {
3408                 case 2:
3409                 {
3410                         /*
3411                          * Update the changestamp.  Emperical tests show that the
3412                          * ChangeID is always updated,but c_setprinter is  
3413                          *  global spooler variable (not per printer).
3414                          */
3415
3416                         /* ChangeID **must** be increasing over the lifetime
3417                            of client's spoolss service in order for the
3418                            client's cache to show updates */
3419
3420                         printer.info_2->changeid = rev_changeid();
3421
3422                         /*
3423                          * Because one day someone will ask:
3424                          * NT->NT       An admin connection to a remote
3425                          *              printer show changes imeediately in
3426                          *              the properities dialog
3427                          *      
3428                          *              A non-admin connection will only show the
3429                          *              changes after viewing the properites page
3430                          *              2 times.  Seems to be related to a
3431                          *              race condition in the client between the spooler
3432                          *              updating the local cache and the Explorer.exe GUI
3433                          *              actually displaying the properties.
3434                          *
3435                          *              This is fixed in Win2k.  admin/non-admin
3436                          *              connections both display changes immediately.
3437                          *
3438                          * 14/12/01     --jerry
3439                          */
3440
3441                         result=update_a_printer_2(printer.info_2);
3442                         
3443                         break;
3444                 }
3445                 default:
3446                         result=WERR_UNKNOWN_LEVEL;
3447                         break;
3448         }
3449         
3450         return result;
3451 }
3452
3453 /****************************************************************************
3454  Initialize printer devmode & data with previously saved driver init values.
3455 ****************************************************************************/
3456
3457 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3458 {
3459         int                     len = 0;
3460         pstring                 key;
3461         TDB_DATA                kbuf, dbuf;
3462         NT_PRINTER_INFO_LEVEL_2 info;
3463
3464
3465         ZERO_STRUCT(info);
3466
3467         /*
3468          * Delete any printer data 'values' already set. When called for driver
3469          * replace, there will generally be some, but during an add printer, there
3470          * should not be any (if there are delete them).
3471          */
3472          
3473         delete_all_printer_data( info_ptr, "" );
3474         
3475         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3476
3477         kbuf.dptr = key;
3478         kbuf.dsize = strlen(key)+1;
3479
3480         dbuf = tdb_fetch(tdb_drivers, kbuf);
3481         if (!dbuf.dptr) {
3482                 /*
3483                  * When changing to a driver that has no init info in the tdb, remove
3484                  * the previous drivers init info and leave the new on blank.
3485                  */
3486                 free_nt_devicemode(&info_ptr->devmode);
3487                 return False;
3488         }
3489         
3490         /*
3491          * Get the saved DEVMODE..
3492          */
3493          
3494         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3495
3496         /*
3497          * The saved DEVMODE contains the devicename from the printer used during
3498          * the initialization save. Change it to reflect the new printer.
3499          */
3500          
3501         if ( info.devmode ) {
3502                 ZERO_STRUCT(info.devmode->devicename);
3503                 fstrcpy(info.devmode->devicename, info_ptr->printername);
3504         }
3505
3506         /*
3507          * NT/2k does not change out the entire DeviceMode of a printer
3508          * when changing the driver.  Only the driverextra, private, & 
3509          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3510          *
3511          * Later examination revealed that Windows NT/2k does reset the
3512          * the printer's device mode, bit **only** when you change a 
3513          * property of the device mode such as the page orientation.
3514          * --jerry
3515          */
3516
3517
3518         /* Bind the saved DEVMODE to the new the printer */
3519          
3520         free_nt_devicemode(&info_ptr->devmode);
3521         info_ptr->devmode = info.devmode;
3522
3523         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3524                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3525
3526         /* Add the printer data 'values' to the new printer */
3527          
3528         len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3529         
3530
3531         SAFE_FREE(dbuf.dptr);
3532
3533         return True;    
3534 }
3535
3536 /****************************************************************************
3537  Initialize printer devmode & data with previously saved driver init values.
3538  When a printer is created using AddPrinter, the drivername bound to the
3539  printer is used to lookup previously saved driver initialization info, which
3540  is bound to the new printer.
3541 ****************************************************************************/
3542
3543 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3544 {
3545         BOOL result = False;
3546         
3547         switch (level) {
3548                 case 2:
3549                         result = set_driver_init_2(printer->info_2);
3550                         break;
3551                         
3552                 default:
3553                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
3554                                 level));
3555                         break;
3556         }
3557         
3558         return result;
3559 }
3560
3561 /****************************************************************************
3562  Delete driver init data stored for a specified driver
3563 ****************************************************************************/
3564
3565 BOOL del_driver_init(char *drivername)
3566 {
3567         pstring key;
3568         TDB_DATA kbuf;
3569
3570         if (!drivername || !*drivername) {
3571                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3572                 return False;
3573         }
3574
3575         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3576
3577         kbuf.dptr = key;
3578         kbuf.dsize = strlen(key)+1;
3579
3580         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3581
3582         return (tdb_delete(tdb_drivers, kbuf) == 0);
3583 }
3584
3585 /****************************************************************************
3586  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
3587  in the tdb. Note: this is different from the driver entry and the printer
3588  entry. There should be a single driver init entry for each driver regardless
3589  of whether it was installed from NT or 2K. Technically, they should be
3590  different, but they work out to the same struct.
3591 ****************************************************************************/
3592
3593 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3594 {
3595         pstring key;
3596         char *buf;
3597         int buflen, len, ret;
3598         TDB_DATA kbuf, dbuf;
3599
3600         buf = NULL;
3601         buflen = 0;
3602
3603  again: 
3604         len = 0;
3605         len += pack_devicemode(info->devmode, buf+len, buflen-len);
3606
3607         len += pack_values( &info->data, buf+len, buflen-len );
3608
3609         if (buflen != len) {
3610                 char *tb;
3611
3612                 tb = (char *)Realloc(buf, len);
3613                 if (!tb) {
3614                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3615                         ret = -1;
3616                         goto done;
3617                 }
3618                 else
3619                         buf = tb;
3620                 buflen = len;
3621                 goto again;
3622         }
3623
3624         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3625
3626         kbuf.dptr = key;
3627         kbuf.dsize = strlen(key)+1;
3628         dbuf.dptr = buf;
3629         dbuf.dsize = len;
3630
3631         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3632
3633 done:
3634         if (ret == -1)
3635                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3636
3637         SAFE_FREE(buf);
3638
3639         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3640                  info->sharename, info->drivername));
3641
3642         return ret;
3643 }
3644
3645 /****************************************************************************
3646  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3647 ****************************************************************************/
3648
3649 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3650 {
3651         uint32 result;
3652         
3653         dump_a_printer(printer, level); 
3654         
3655         switch (level) {
3656                 case 2:
3657                         result = update_driver_init_2(printer.info_2);
3658                         break;
3659                 default:
3660                         result = 1;
3661                         break;
3662         }
3663         
3664         return result;
3665 }
3666
3667 /****************************************************************************
3668  Convert the printer data value, a REG_BINARY array, into an initialization 
3669  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3670  got to keep the endians happy :).
3671 ****************************************************************************/
3672
3673 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3674 {
3675         BOOL       result = False;
3676         prs_struct ps;
3677         DEVICEMODE devmode;
3678
3679         ZERO_STRUCT(devmode);
3680
3681         prs_init(&ps, 0, ctx, UNMARSHALL);
3682         ps.data_p      = (char *)data;
3683         ps.buffer_size = data_len;
3684
3685         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3686                 result = convert_devicemode("", &devmode, &nt_devmode);
3687         else
3688                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3689
3690         return result;
3691 }
3692
3693 /****************************************************************************
3694  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3695
3696  1. Use the driver's config DLL to this UNC printername and:
3697     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3698     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3699  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3700
3701  The last step triggers saving the "driver initialization" information for
3702  this printer into the tdb. Later, new printers that use this driver will
3703  have this initialization information bound to them. This simulates the
3704  driver initialization, as if it had run on the Samba server (as it would
3705  have done on NT).
3706
3707  The Win32 client side code requirement sucks! But until we can run arbitrary
3708  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3709  
3710  It would have been easier to use SetPrinter because all the UNMARSHALLING of
3711  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3712  about it and you will realize why.  JRR 010720
3713 ****************************************************************************/
3714
3715 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3716 {
3717         WERROR        status       = WERR_OK;
3718         TALLOC_CTX    *ctx         = NULL;
3719         NT_DEVICEMODE *nt_devmode  = NULL;
3720         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3721         
3722         /*
3723          * When the DEVMODE is already set on the printer, don't try to unpack it.
3724          */
3725         DEBUG(8,("save_driver_init_2: Enter...\n"));
3726         
3727         if ( !printer->info_2->devmode && data_len ) {
3728                 /*
3729                  * Set devmode on printer info, so entire printer initialization can be
3730                  * saved to tdb.
3731                  */
3732
3733                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3734                         return WERR_NOMEM;
3735
3736                 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3737                         status = WERR_NOMEM;
3738                         goto done;
3739                 }
3740         
3741                 ZERO_STRUCTP(nt_devmode);
3742
3743                 /*
3744                  * The DEVMODE is held in the 'data' component of the param in raw binary.
3745                  * Convert it to to a devmode structure
3746                  */
3747                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3748                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3749                         status = WERR_INVALID_PARAM;
3750                         goto done;
3751                 }
3752
3753                 printer->info_2->devmode = nt_devmode;
3754         }
3755
3756         /*
3757          * Pack up and add (or update) the DEVMODE and any current printer data to
3758          * a 'driver init' element in the tdb
3759          * 
3760          */
3761
3762         if ( update_driver_init(*printer, 2) != 0 ) {
3763                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3764                 status = WERR_NOMEM;
3765                 goto done;
3766         }
3767         
3768         /*
3769          * If driver initialization info was successfully saved, set the current 
3770          * printer to match it. This allows initialization of the current printer 
3771          * as well as the driver.
3772          */
3773         status = mod_a_printer(*printer, 2);
3774         if (!W_ERROR_IS_OK(status)) {
3775                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3776                                   printer->info_2->printername));
3777         }
3778         
3779   done:
3780         talloc_destroy(ctx);
3781         free_nt_devicemode( &nt_devmode );
3782         
3783         printer->info_2->devmode = tmp_devmode;
3784
3785         return status;
3786 }
3787
3788 /****************************************************************************
3789  Update the driver init info (DEVMODE and specifics) for a printer
3790 ****************************************************************************/
3791
3792 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3793 {
3794         WERROR status = WERR_OK;
3795         
3796         switch (level) {
3797                 case 2:
3798                         status = save_driver_init_2( printer, data, data_len );
3799                         break;
3800                 default:
3801                         status = WERR_UNKNOWN_LEVEL;
3802                         break;
3803         }
3804         
3805         return status;
3806 }
3807
3808 /****************************************************************************
3809  Deep copy a NT_PRINTER_DATA
3810 ****************************************************************************/
3811
3812 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3813 {
3814         int i, j, num_vals, new_key_index;
3815         REGVAL_CTR *src_key, *dst_key;
3816         
3817         if ( !dst || !src )
3818                 return NT_STATUS_NO_MEMORY;
3819         
3820         for ( i=0; i<src->num_keys; i++ ) {
3821                            
3822                 /* create a new instance of the printerkey in the destination 
3823                    printer_data object */
3824                    
3825                 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3826                 dst_key = &dst->keys[new_key_index].values;
3827
3828                 src_key = &src->keys[i].values;
3829                 num_vals = regval_ctr_numvals( src_key );
3830                 
3831                 /* dup the printer entire printer key */
3832                 
3833                 for ( j=0; j<num_vals; j++ ) {
3834                         regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3835                 }
3836         }
3837                 
3838         return NT_STATUS_OK;
3839 }
3840
3841 /****************************************************************************
3842  Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3843  Caller must free.
3844 ****************************************************************************/
3845
3846 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3847 {
3848         NT_PRINTER_INFO_LEVEL_2 *copy;
3849         
3850         if ( !printer )
3851                 return NULL;
3852         
3853         if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3854                 return NULL;
3855                 
3856         memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3857         
3858         /* malloc()'d members copied here */
3859         
3860         copy->devmode = dup_nt_devicemode( printer->devmode );  
3861
3862         ZERO_STRUCT( copy->data );
3863         copy_printer_data( &copy->data, &printer->data );
3864         
3865         /* this is talloc()'d; very ugly that we have a structure that 
3866            is half malloc()'d and half talloc()'d but that is the way 
3867            that the PRINTER_INFO stuff is written right now.  --jerry  */
3868            
3869         copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3870                 
3871         return copy;
3872 }
3873
3874 /****************************************************************************
3875  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3876 ****************************************************************************/
3877
3878 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
3879                         const char *sharename)
3880 {
3881         WERROR result;
3882         NT_PRINTER_INFO_LEVEL *printer = NULL;
3883         
3884         *pp_printer = NULL;
3885
3886         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3887
3888         switch (level) {
3889                 case 2:
3890                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3891                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
3892                                 return WERR_NOMEM;
3893                         }
3894                         ZERO_STRUCTP(printer);
3895                         
3896                         /* 
3897                          * check for cache first.  A Printer handle cannot changed
3898                          * to another printer object so we only check that the printer 
3899                          * is actually for a printer and that the printer_info pointer 
3900                          * is valid
3901                          */
3902                         if ( print_hnd 
3903                                 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER) 
3904                                 && print_hnd->printer_info )
3905                         {
3906                                 if ( !(printer->info_2 = dup_printer_2(print_hnd->ctx, print_hnd->printer_info->info_2)) ) {
3907                                         DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3908                                         
3909                                         SAFE_FREE(printer);
3910                                         return WERR_NOMEM;
3911                                 }
3912                                 
3913                                 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3914                                 
3915                                 *pp_printer = printer;                          
3916                                 result = WERR_OK;
3917                                 
3918                                 break;
3919                         }
3920
3921                         /* no cache for this handle; see if we can match one from another handle */
3922                         
3923                         if ( print_hnd )
3924                                 result = find_printer_in_print_hnd_cache(print_hnd->ctx, &printer->info_2, sharename);
3925                         
3926                         /* fail to disk if we don't have it with any open handle */
3927
3928                         if ( !print_hnd || !W_ERROR_IS_OK(result) )
3929                                 result = get_a_printer_2(&printer->info_2, sharename);                          
3930                         
3931                         /* we have a new printer now.  Save it with this handle */
3932                         
3933                         if ( W_ERROR_IS_OK(result) ) {
3934                                 dump_a_printer(*printer, level);
3935                                         
3936                                 /* save a copy in cache */
3937                                 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
3938                                         if ( !print_hnd->printer_info )
3939                                                 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
3940
3941                                         if ( print_hnd->printer_info ) {
3942                                                 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
3943                                                 
3944                                                 /* don't fail the lookup just because the cache update failed */
3945                                                 if ( !print_hnd->printer_info->info_2 )
3946                                                         DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
3947                                         }
3948                                 }
3949                                 *pp_printer = printer;  
3950                         }
3951                         else
3952                                 SAFE_FREE(printer);
3953                         
3954                         break;
3955                         
3956                 default:
3957                         result=WERR_UNKNOWN_LEVEL;
3958                         break;
3959         }
3960         
3961         DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3962
3963         return result;
3964 }
3965
3966 /****************************************************************************
3967  Deletes a NT_PRINTER_INFO_LEVEL struct.
3968 ****************************************************************************/
3969
3970 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3971 {
3972         uint32 result;
3973         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3974
3975         DEBUG(104,("freeing a printer at level [%d]\n", level));
3976
3977         if (printer == NULL)
3978                 return 0;
3979         
3980         switch (level) {
3981                 case 2:
3982                         if (printer->info_2 != NULL) {
3983                                 free_nt_printer_info_level_2(&printer->info_2);
3984                                 result=0;
3985                         } else
3986                                 result=4;
3987                         break;
3988
3989                 default:
3990                         result=1;
3991                         break;
3992         }
3993
3994         SAFE_FREE(*pp_printer);
3995         return result;
3996 }
3997
3998 /****************************************************************************
3999 ****************************************************************************/
4000 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4001 {
4002         uint32 result;
4003         DEBUG(104,("adding a printer at level [%d]\n", level));
4004         dump_a_printer_driver(driver, level);
4005         
4006         switch (level) {
4007                 case 3:
4008                         result=add_a_printer_driver_3(driver.info_3);
4009                         break;
4010
4011                 case 6:
4012                         result=add_a_printer_driver_6(driver.info_6);
4013                         break;
4014
4015                 default:
4016                         result=1;
4017                         break;
4018         }
4019         
4020         return result;
4021 }
4022 /****************************************************************************
4023 ****************************************************************************/
4024
4025 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4026                             fstring drivername, const char *architecture, uint32 version)
4027 {
4028         WERROR result;
4029         
4030         switch (level) {
4031                 case 3:
4032                         /* Sometime we just want any version of the driver */
4033                         
4034                         if ( version == DRIVER_ANY_VERSION ) {
4035                                 /* look for Win2k first and then for NT4 */
4036                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4037                                                 architecture, 3);
4038                                                 
4039                                 if ( !W_ERROR_IS_OK(result) ) {
4040                                         result = get_a_printer_driver_3( &driver->info_3, 
4041                                                         drivername, architecture, 2 );
4042                                 }
4043                         } else {
4044                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4045                                         architecture, version);                         
4046                         }
4047                         break;
4048                         
4049                 default:
4050                         result=W_ERROR(1);
4051                         break;
4052         }
4053         
4054         if (W_ERROR_IS_OK(result))
4055                 dump_a_printer_driver(*driver, level);
4056                 
4057         return result;
4058 }
4059
4060 /****************************************************************************
4061 ****************************************************************************/
4062 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4063 {
4064         uint32 result;
4065         
4066         switch (level) {
4067                 case 3:
4068                 {
4069                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4070                         if (driver.info_3 != NULL)
4071                         {
4072                                 info3=driver.info_3;
4073                                 SAFE_FREE(info3->dependentfiles);
4074                                 ZERO_STRUCTP(info3);
4075                                 SAFE_FREE(info3);
4076                                 result=0;
4077                         } else {
4078                                 result=4;
4079                         }
4080                         break;
4081                 }
4082                 case 6:
4083                 {
4084                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4085                         if (driver.info_6 != NULL) {
4086                                 info6=driver.info_6;
4087                                 SAFE_FREE(info6->dependentfiles);
4088                                 SAFE_FREE(info6->previousnames);
4089                                 ZERO_STRUCTP(info6);
4090                                 SAFE_FREE(info6);
4091                                 result=0;
4092                         } else {
4093                                 result=4;
4094                         }
4095                         break;
4096                 }
4097                 default:
4098                         result=1;
4099                         break;
4100         }
4101         return result;
4102 }
4103
4104
4105 /****************************************************************************
4106   Determine whether or not a particular driver is currently assigned
4107   to a printer
4108 ****************************************************************************/
4109
4110 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4111 {
4112         int snum;
4113         int n_services = lp_numservices();
4114         NT_PRINTER_INFO_LEVEL *printer = NULL;
4115
4116         if ( !info_3 ) 
4117                 return False;
4118
4119         DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4120         
4121         /* loop through the printers.tdb and check for the drivername */
4122         
4123         for (snum=0; snum<n_services; snum++) {
4124                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4125                         continue;
4126                 
4127                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4128                         continue;
4129                 
4130                 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4131                         free_a_printer( &printer, 2 );
4132                         return True;
4133                 }
4134                 
4135                 free_a_printer( &printer, 2 );
4136         }
4137         
4138         DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4139         
4140         /* report that the driver is not in use by default */
4141         
4142         return False;
4143 }
4144
4145
4146 /**********************************************************************
4147  Check to see if a ogiven file is in use by *info
4148  *********************************************************************/
4149  
4150 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4151 {
4152         int i = 0;
4153         
4154         if ( !info )
4155                 return False;
4156                 
4157         if ( strequal(file, info->driverpath) )
4158                 return True;
4159
4160         if ( strequal(file, info->datafile) )
4161                 return True;
4162
4163         if ( strequal(file, info->configfile) )
4164                 return True;
4165
4166         if ( strequal(file, info->helpfile) )
4167                 return True;
4168         
4169         /* see of there are any dependent files to examine */
4170         
4171         if ( !info->dependentfiles )
4172                 return False;
4173         
4174         while ( *info->dependentfiles[i] ) {
4175                 if ( strequal(file, info->dependentfiles[i]) )
4176                         return True;
4177                 i++;
4178         }
4179         
4180         return False;
4181
4182 }
4183
4184 /**********************************************************************
4185  Utility function to remove the dependent file pointed to by the 
4186  input parameter from the list 
4187  *********************************************************************/
4188
4189 static void trim_dependent_file( fstring files[], int idx )
4190 {
4191         
4192         /* bump everything down a slot */
4193
4194         while( *files[idx+1] ) {
4195                 fstrcpy( files[idx], files[idx+1] );
4196                 idx++;
4197         }
4198         
4199         *files[idx] = '\0';
4200
4201         return; 
4202 }
4203
4204 /**********************************************************************
4205  Check if any of the files used by src are also used by drv 
4206  *********************************************************************/
4207
4208 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4209                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4210 {
4211         BOOL    in_use = False;
4212         int     i = 0;
4213         
4214         if ( !src || !drv )
4215                 return False;
4216                 
4217         /* check each file.  Remove it from the src structure if it overlaps */
4218         
4219         if ( drv_file_in_use(src->driverpath, drv) ) {
4220                 in_use = True;
4221                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4222                 fstrcpy( src->driverpath, "" );
4223         }
4224                 
4225         if ( drv_file_in_use(src->datafile, drv) ) {
4226                 in_use = True;
4227                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4228                 fstrcpy( src->datafile, "" );
4229         }
4230                 
4231         if ( drv_file_in_use(src->configfile, drv) ) {
4232                 in_use = True;
4233                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4234                 fstrcpy( src->configfile, "" );
4235         }
4236                 
4237         if ( drv_file_in_use(src->helpfile, drv) ) {
4238                 in_use = True;
4239                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4240                 fstrcpy( src->helpfile, "" );
4241         }
4242         
4243         /* are there any dependentfiles to examine? */
4244         
4245         if ( !src->dependentfiles )
4246                 return in_use;
4247                 
4248         while ( *src->dependentfiles[i] ) {
4249                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4250                         in_use = True;
4251                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4252                         trim_dependent_file( src->dependentfiles, i );
4253                 } else
4254                         i++;
4255         }               
4256                 
4257         return in_use;
4258 }
4259
4260 /****************************************************************************
4261   Determine whether or not a particular driver files are currently being 
4262   used by any other driver.  
4263   
4264   Return value is True if any files were in use by other drivers
4265   and False otherwise.
4266   
4267   Upon return, *info has been modified to only contain the driver files
4268   which are not in use
4269 ****************************************************************************/
4270
4271 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4272 {
4273         int                             i;
4274         int                             ndrivers;
4275         uint32                          version;
4276         fstring                         *list = NULL;
4277         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4278         
4279         if ( !info )
4280                 return False;
4281         
4282         version = info->cversion;
4283         
4284         /* loop over all driver versions */
4285         
4286         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4287         
4288         /* get the list of drivers */
4289                 
4290         list = NULL;
4291         ndrivers = get_ntdrivers(&list, info->environment, version);
4292                 
4293         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4294                 ndrivers, info->environment, version));
4295
4296         /* check each driver for overlap in files */
4297                 
4298         for (i=0; i<ndrivers; i++) {
4299                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4300                         
4301                 ZERO_STRUCT(driver);
4302                         
4303                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4304                         SAFE_FREE(list);
4305                         return True;
4306                 }
4307                         
4308                 /* check if d2 uses any files from d1 */
4309                 /* only if this is a different driver than the one being deleted */
4310                         
4311                 if ( !strequal(info->name, driver.info_3->name) ) {
4312                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4313                                 free_a_printer_driver(driver, 3);
4314                                 SAFE_FREE( list );
4315                                 return True;
4316                         }
4317                 }
4318         
4319                 free_a_printer_driver(driver, 3);
4320         }       
4321         
4322         SAFE_FREE(list);
4323         
4324         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4325         
4326         driver.info_3 = info;
4327         
4328         if ( DEBUGLEVEL >= 20 )
4329                 dump_a_printer_driver( driver, 3 );
4330         
4331         return False;
4332 }
4333
4334 /****************************************************************************
4335   Actually delete the driver files.  Make sure that 
4336   printer_driver_files_in_use() return False before calling 
4337   this.
4338 ****************************************************************************/
4339
4340 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4341 {
4342         int i = 0;
4343         char *s;
4344         connection_struct *conn;
4345         DATA_BLOB null_pw;
4346         NTSTATUS nt_status;
4347         fstring res_type;
4348
4349         if ( !info_3 )
4350                 return False;
4351                 
4352         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4353         
4354         /*
4355          * Connect to the print$ share under the same account as the 
4356          * user connected to the rpc pipe. Note we must be root to 
4357          * do this.
4358          */
4359          
4360         null_pw = data_blob( NULL, 0 );
4361         fstrcpy(res_type, "A:");
4362         become_root();
4363         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4364         unbecome_root();
4365         
4366         if ( !conn ) {
4367                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4368                 return False;
4369         }
4370
4371         /* Save who we are - we are temporarily becoming the connection user. */
4372
4373         if ( !become_user(conn, conn->vuid) ) {
4374                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4375                 return False;
4376         }
4377
4378         /* now delete the files; must strip the '\print$' string from 
4379            fron of path                                                */
4380         
4381         if ( *info_3->driverpath ) {
4382                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4383                         DEBUG(10,("deleting driverfile [%s]\n", s));
4384                         unlink_internals(conn, 0, s);
4385                 }
4386         }
4387                 
4388         if ( *info_3->configfile ) {
4389                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4390                         DEBUG(10,("deleting configfile [%s]\n", s));
4391                         unlink_internals(conn, 0, s);
4392                 }
4393         }
4394         
4395         if ( *info_3->datafile ) {
4396                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4397                         DEBUG(10,("deleting datafile [%s]\n", s));
4398                         unlink_internals(conn, 0, s);
4399                 }
4400         }
4401         
4402         if ( *info_3->helpfile ) {
4403                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4404                         DEBUG(10,("deleting helpfile [%s]\n", s));
4405                         unlink_internals(conn, 0, s);
4406                 }
4407         }
4408         
4409         /* check if we are done removing files */
4410         
4411         if ( info_3->dependentfiles ) {
4412                 while ( *info_3->dependentfiles[i] ) {
4413                         char *file;
4414
4415                         /* bypass the "\print$" portion of the path */
4416                         
4417                         if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4418                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4419                                 unlink_internals(conn, 0, file );
4420                         }
4421                         
4422                         i++;
4423                 }
4424         }
4425
4426         unbecome_user();
4427         
4428         return True;
4429 }
4430
4431 /****************************************************************************
4432  Remove a printer driver from the TDB.  This assumes that the the driver was
4433  previously looked up.
4434  ***************************************************************************/
4435
4436 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4437                               uint32 version, BOOL delete_files )
4438 {
4439         pstring         key;
4440         const char     *arch;
4441         TDB_DATA        kbuf, dbuf;
4442         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4443
4444         /* delete the tdb data first */
4445
4446         arch = get_short_archi(info_3->environment);
4447         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4448                 arch, version, info_3->name);
4449
4450         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4451                 key, delete_files ? "TRUE" : "FALSE" ));
4452
4453         ctr.info_3 = info_3;
4454         dump_a_printer_driver( ctr, 3 );
4455
4456         kbuf.dptr=key;
4457         kbuf.dsize=strlen(key)+1;
4458
4459         /* check if the driver actually exists for this environment */
4460         
4461         dbuf = tdb_fetch( tdb_drivers, kbuf );
4462         if ( !dbuf.dptr ) {
4463                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4464                 return WERR_UNKNOWN_PRINTER_DRIVER;
4465         }
4466                 
4467         SAFE_FREE( dbuf.dptr );
4468         
4469         /* ok... the driver exists so the delete should return success */
4470                 
4471         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4472                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4473                 return WERR_ACCESS_DENIED;
4474         }
4475
4476         /*
4477          * now delete any associated files if delete_files == True
4478          * even if this part failes, we return succes because the
4479          * driver doesn not exist any more
4480          */
4481
4482         if ( delete_files )
4483                 delete_driver_files( info_3, user );
4484                         
4485                 
4486         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4487
4488         return WERR_OK;
4489         }
4490         
4491 /****************************************************************************
4492  Store a security desc for a printer.
4493 ****************************************************************************/
4494
4495 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4496 {
4497         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4498         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4499         prs_struct ps;
4500         TALLOC_CTX *mem_ctx = NULL;
4501         fstring key;
4502         WERROR status;
4503
4504         mem_ctx = talloc_init("nt_printing_setsec");
4505         if (mem_ctx == NULL)
4506                 return WERR_NOMEM;
4507
4508         /* The old owner and group sids of the security descriptor are not
4509            present when new ACEs are added or removed by changing printer
4510            permissions through NT.  If they are NULL in the new security
4511            descriptor then copy them over from the old one. */
4512
4513         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4514                 DOM_SID *owner_sid, *group_sid;
4515                 SEC_ACL *dacl, *sacl;
4516                 SEC_DESC *psd = NULL;
4517                 size_t size;
4518
4519                 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4520
4521                 /* Pick out correct owner and group sids */
4522
4523                 owner_sid = secdesc_ctr->sec->owner_sid ?
4524                         secdesc_ctr->sec->owner_sid :
4525                         old_secdesc_ctr->sec->owner_sid;
4526
4527                 group_sid = secdesc_ctr->sec->grp_sid ?
4528                         secdesc_ctr->sec->grp_sid :
4529                         old_secdesc_ctr->sec->grp_sid;
4530
4531                 dacl = secdesc_ctr->sec->dacl ?
4532                         secdesc_ctr->sec->dacl :
4533                         old_secdesc_ctr->sec->dacl;
4534
4535                 sacl = secdesc_ctr->sec->sacl ?
4536                         secdesc_ctr->sec->sacl :
4537                         old_secdesc_ctr->sec->sacl;
4538
4539                 /* Make a deep copy of the security descriptor */
4540
4541                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
4542                                     owner_sid, group_sid,
4543                                     sacl,
4544                                     dacl,
4545                                     &size);
4546
4547                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4548         }
4549
4550         if (!new_secdesc_ctr) {
4551                 new_secdesc_ctr = secdesc_ctr;
4552         }
4553
4554         /* Store the security descriptor in a tdb */
4555
4556         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4557                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4558
4559         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4560                              &ps, 1)) {
4561                 status = WERR_BADFUNC;
4562                 goto out;
4563         }
4564
4565         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4566
4567         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4568                 status = WERR_OK;
4569         } else {
4570                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4571                 status = WERR_BADFUNC;
4572         }
4573
4574         /* Free malloc'ed memory */
4575
4576  out:
4577
4578         prs_mem_free(&ps);
4579         if (mem_ctx)
4580                 talloc_destroy(mem_ctx);
4581         return status;
4582 }
4583
4584 /****************************************************************************
4585  Construct a default security descriptor buffer for a printer.
4586 ****************************************************************************/
4587
4588 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4589 {
4590         SEC_ACE ace[3];
4591         SEC_ACCESS sa;
4592         SEC_ACL *psa = NULL;
4593         SEC_DESC_BUF *sdb = NULL;
4594         SEC_DESC *psd = NULL;
4595         DOM_SID owner_sid;
4596         size_t sd_size;
4597
4598         /* Create an ACE where Everyone is allowed to print */
4599
4600         init_sec_access(&sa, PRINTER_ACE_PRINT);
4601         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4602                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4603
4604         /* Make the security descriptor owned by the Administrators group
4605            on the PDC of the domain. */
4606
4607         if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4608                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4609         } else {
4610
4611                 /* Backup plan - make printer owned by admins.
4612                    This should emulate a lanman printer as security
4613                    settings can't be changed. */
4614
4615                 sid_copy(&owner_sid, get_global_sam_sid());
4616                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4617         }
4618
4619         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4620         init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4621                      sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4622                      SEC_ACE_FLAG_INHERIT_ONLY);
4623
4624         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4625         init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4626                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4627
4628         /* The ACL revision number in rpc_secdesc.h differs from the one
4629            created by NT when setting ACE entries in printer
4630            descriptors.  NT4 complains about the property being edited by a
4631            NT5 machine. */
4632
4633         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4634                 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4635                                     &owner_sid, NULL,
4636                                     NULL, psa, &sd_size);
4637         }
4638
4639         if (!psd) {
4640                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4641                 return NULL;
4642         }
4643
4644         sdb = make_sec_desc_buf(ctx, sd_size, psd);
4645
4646         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4647                  (unsigned int)sd_size));
4648
4649         return sdb;
4650 }
4651
4652 /****************************************************************************
4653  Get a security desc for a printer.
4654 ****************************************************************************/
4655
4656 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4657 {
4658         prs_struct ps;
4659         fstring key;
4660         char *temp;
4661
4662         if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4663                 printername = temp + 1;
4664         }
4665
4666         /* Fetch security descriptor from tdb */
4667
4668         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4669
4670         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4671             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4672
4673                 DEBUG(4,("using default secdesc for %s\n", printername));
4674
4675                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4676                         return False;
4677                 }
4678
4679                 /* Save default security descriptor for later */
4680
4681                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4682                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4683
4684                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4685                         tdb_prs_store(tdb_printers, key, &ps);
4686
4687                 prs_mem_free(&ps);
4688
4689                 return True;
4690         }
4691
4692         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4693            this security descriptor has been created when winbindd was
4694            down.  Take ownership of security descriptor. */
4695
4696         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4697                 DOM_SID owner_sid;
4698
4699                 /* Change sd owner to workgroup administrator */
4700
4701                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4702                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4703                         SEC_DESC *psd = NULL;
4704                         size_t size;
4705
4706                         /* Create new sd */
4707
4708                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4709
4710                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4711                                             &owner_sid,
4712                                             (*secdesc_ctr)->sec->grp_sid,
4713                                             (*secdesc_ctr)->sec->sacl,
4714                                             (*secdesc_ctr)->sec->dacl,
4715                                             &size);
4716
4717                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4718
4719                         /* Swap with other one */
4720
4721                         *secdesc_ctr = new_secdesc_ctr;
4722
4723                         /* Set it */
4724
4725                         nt_printing_setsec(printername, *secdesc_ctr);
4726                 }
4727         }
4728
4729         if (DEBUGLEVEL >= 10) {
4730                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4731                 int i;
4732
4733                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4734                            printername, the_acl->num_aces));
4735
4736                 for (i = 0; i < the_acl->num_aces; i++) {
4737                         fstring sid_str;
4738
4739                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4740
4741                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4742                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
4743                                    the_acl->ace[i].info.mask)); 
4744                 }
4745         }
4746
4747         prs_mem_free(&ps);
4748         return True;
4749 }
4750
4751 /* error code:
4752         0: everything OK
4753         1: level not implemented
4754         2: file doesn't exist
4755         3: can't allocate memory
4756         4: can't free memory
4757         5: non existant struct
4758 */
4759
4760 /*
4761         A printer and a printer driver are 2 different things.
4762         NT manages them separatelly, Samba does the same.
4763         Why ? Simply because it's easier and it makes sense !
4764         
4765         Now explanation: You have 3 printers behind your samba server,
4766         2 of them are the same make and model (laser A and B). But laser B
4767         has an 3000 sheet feeder and laser A doesn't such an option.
4768         Your third printer is an old dot-matrix model for the accounting :-).
4769         
4770         If the /usr/local/samba/lib directory (default dir), you will have
4771         5 files to describe all of this.
4772         
4773         3 files for the printers (1 by printer):
4774                 NTprinter_laser A
4775                 NTprinter_laser B
4776                 NTprinter_accounting
4777         2 files for the drivers (1 for the laser and 1 for the dot matrix)
4778                 NTdriver_printer model X
4779                 NTdriver_printer model Y
4780
4781 jfm: I should use this comment for the text file to explain
4782         same thing for the forms BTW.
4783         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4784
4785 */
4786
4787 /* Convert generic access rights to printer object specific access rights.
4788    It turns out that NT4 security descriptors use generic access rights and
4789    NT5 the object specific ones. */
4790
4791 void map_printer_permissions(SEC_DESC *sd)
4792 {
4793         int i;
4794
4795         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4796                 se_map_generic(&sd->dacl->ace[i].info.mask,
4797                                &printer_generic_mapping);
4798         }
4799 }
4800
4801 /****************************************************************************
4802  Check a user has permissions to perform the given operation.  We use the
4803  permission constants defined in include/rpc_spoolss.h to check the various
4804  actions we perform when checking printer access.
4805
4806    PRINTER_ACCESS_ADMINISTER:
4807        print_queue_pause, print_queue_resume, update_printer_sec,
4808        update_printer, spoolss_addprinterex_level_2,
4809        _spoolss_setprinterdata
4810
4811    PRINTER_ACCESS_USE:
4812        print_job_start
4813
4814    JOB_ACCESS_ADMINISTER:
4815        print_job_delete, print_job_pause, print_job_resume,
4816        print_queue_purge
4817
4818  ****************************************************************************/
4819 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4820 {
4821         SEC_DESC_BUF *secdesc = NULL;
4822         uint32 access_granted;
4823         NTSTATUS status;
4824         BOOL result;
4825         const char *pname;
4826         TALLOC_CTX *mem_ctx = NULL;
4827         extern struct current_user current_user;
4828         
4829         /* If user is NULL then use the current_user structure */
4830
4831         if (!user)
4832                 user = &current_user;
4833
4834         /* Always allow root or printer admins to do anything */
4835
4836         if (user->uid == 0 ||
4837             user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4838                 return True;
4839         }
4840
4841         /* Get printer name */
4842
4843         pname = PRINTERNAME(snum);
4844
4845         if (!pname || !*pname) {
4846                 errno = EACCES;
4847                 return False;
4848         }
4849
4850         /* Get printer security descriptor */
4851
4852         if(!(mem_ctx = talloc_init("print_access_check"))) {
4853                 errno = ENOMEM;
4854                 return False;
4855         }
4856
4857         nt_printing_getsec(mem_ctx, pname, &secdesc);
4858
4859         if (access_type == JOB_ACCESS_ADMINISTER) {
4860                 SEC_DESC_BUF *parent_secdesc = secdesc;
4861
4862                 /* Create a child security descriptor to check permissions
4863                    against.  This is because print jobs are child objects
4864                    objects of a printer. */
4865
4866                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4867
4868                 /* Now this is the bit that really confuses me.  The access
4869                    type needs to be changed from JOB_ACCESS_ADMINISTER to
4870                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
4871                    to do with the child (job) object becoming like a
4872                    printer??  -tpot */
4873
4874                 access_type = PRINTER_ACCESS_ADMINISTER;
4875         }
4876         
4877         /* Check access */
4878         
4879         map_printer_permissions(secdesc->sec);
4880
4881         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4882                                  &access_granted, &status);
4883
4884         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4885
4886         talloc_destroy(mem_ctx);
4887         
4888         if (!result)
4889                 errno = EACCES;
4890
4891         return result;
4892 }
4893
4894 /****************************************************************************
4895  Check the time parameters allow a print operation.
4896 *****************************************************************************/
4897
4898 BOOL print_time_access_check(int snum)
4899 {
4900         NT_PRINTER_INFO_LEVEL *printer = NULL;
4901         BOOL ok = False;
4902         time_t now = time(NULL);
4903         struct tm *t;
4904         uint32 mins;
4905
4906         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
4907                 return False;
4908
4909         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4910                 ok = True;
4911
4912         t = gmtime(&now);
4913         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4914
4915         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4916                 ok = True;
4917
4918         free_a_printer(&printer, 2);
4919
4920         if (!ok)
4921                 errno = EACCES;
4922
4923         return ok;
4924 }
4925