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