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