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