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