merge of phant0m key fix from APP_HEAD
[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, j;
2427         int     key_len;
2428         int     num_subkeys = 0;
2429         char    *p;
2430         fstring *ptr, *subkeys_ptr = NULL;
2431         fstring subkeyname;
2432         
2433         if ( !data )
2434                 return 0;
2435                 
2436         for ( i=0; i<data->num_keys; i++ ) 
2437         {
2438                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 )
2439                 {
2440                         /* match sure it is a subkey and not the key itself */
2441                         
2442                         key_len = strlen( key );
2443                         if ( strlen(data->keys[i].name) == key_len )
2444                                 continue;
2445                         
2446                         /* get subkey path */
2447
2448                         p = data->keys[i].name + key_len;
2449                         if ( *p == '\\' )
2450                                 p++;
2451                         fstrcpy( subkeyname, p );
2452                         if ( (p = strchr( subkeyname, '\\' )) )
2453                                 *p = '\0';
2454                         
2455                         /* don't add a key more than once */
2456                         
2457                         for ( j=0; j<num_subkeys; j++ ) {
2458                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2459                                         break;
2460                         }
2461                         
2462                         if ( j != num_subkeys )
2463                                 continue;
2464
2465                         /* found a match, so allocate space and copy the name */
2466                         
2467                         if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2468                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2469                                         num_subkeys+1));
2470                                 SAFE_FREE( subkeys );
2471                                 return 0;
2472                         }
2473                         
2474                         subkeys_ptr = ptr;
2475                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2476                         num_subkeys++;
2477                 }
2478                 
2479         }
2480         
2481         /* tag of the end */
2482         
2483         fstrcpy( subkeys_ptr[num_subkeys], "" );
2484         
2485         *subkeys = subkeys_ptr;
2486
2487         return num_subkeys;
2488 }
2489  
2490 /****************************************************************************
2491  ***************************************************************************/
2492  
2493 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key )
2494 {
2495         NT_PRINTER_DATA *data;
2496         int             i;
2497         int             removed_keys = 0;
2498         int             empty_slot;
2499         
2500         data = &p2->data;
2501         empty_slot = data->num_keys;
2502
2503         if ( !key )
2504                 return WERR_INVALID_PARAM;
2505         
2506         /* remove all keys */
2507
2508         if ( !strlen(key) ) 
2509         {
2510                 for ( i=0; i<data->num_keys; i++ ) 
2511                 {
2512                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2513                                 data->keys[i].name));
2514                 
2515                         SAFE_FREE( data->keys[i].name );
2516                         regval_ctr_destroy( &data->keys[i].values );
2517                 }
2518         
2519                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2520                         p2->printername ));
2521         
2522                 SAFE_FREE( data->keys );
2523                 ZERO_STRUCTP( data );
2524
2525                 return WERR_OK;
2526         }
2527
2528         /* remove a specific key (and all subkeys) */
2529         
2530         for ( i=0; i<data->num_keys; i++ ) 
2531         {
2532                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 )
2533                 {
2534                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2535                                 data->keys[i].name));
2536                 
2537                         SAFE_FREE( data->keys[i].name );
2538                         regval_ctr_destroy( &data->keys[i].values );
2539                 
2540                         /* mark the slot as empty */
2541
2542                         ZERO_STRUCTP( &data->keys[i] );
2543                 }
2544         }
2545
2546         /* find the first empty slot */
2547
2548         for ( i=0; i<data->num_keys; i++ ) {
2549                 if ( !data->keys[i].name ) {
2550                         empty_slot = i;
2551                         removed_keys++;
2552                         break;
2553                 }
2554         }
2555
2556         if ( i == data->num_keys )
2557                 /* nothing was removed */
2558                 return WERR_INVALID_PARAM;
2559
2560         /* move everything down */
2561         
2562         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2563                 if ( data->keys[i].name ) {
2564                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
2565                         ZERO_STRUCTP( &data->keys[i] );
2566                         empty_slot++;
2567                         removed_keys++;
2568                 }
2569         }
2570
2571         /* update count */
2572                 
2573         data->num_keys -= removed_keys;
2574
2575         /* sanity check to see if anything is left */
2576
2577         if ( !data->num_keys )
2578         {
2579                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2580
2581                 SAFE_FREE( data->keys );
2582                 ZERO_STRUCTP( data );
2583         }
2584
2585         return WERR_OK;
2586 }
2587
2588 /****************************************************************************
2589  ***************************************************************************/
2590  
2591 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value )
2592 {
2593         WERROR          result = WERR_OK;
2594         int             key_index;
2595         
2596         /* we must have names on non-zero length */
2597         
2598         if ( !key || !*key|| !value || !*value )
2599                 return WERR_INVALID_NAME;
2600                 
2601         /* find the printer key first */
2602
2603         key_index = lookup_printerkey( &p2->data, key );
2604         if ( key_index == -1 )
2605                 return WERR_OK;
2606                 
2607         regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2608         
2609         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2610                 key, value ));
2611         
2612         return result;
2613 }
2614
2615 /****************************************************************************
2616  ***************************************************************************/
2617  
2618 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value, 
2619                            uint32 type, uint8 *data, int real_len )
2620 {
2621         WERROR          result = WERR_OK;
2622         int             key_index;
2623
2624         /* we must have names on non-zero length */
2625         
2626         if ( !key || !*key|| !value || !*value )
2627                 return WERR_INVALID_NAME;
2628                 
2629         /* find the printer key first */
2630         
2631         key_index = lookup_printerkey( &p2->data, key );
2632         if ( key_index == -1 )
2633                 key_index = add_new_printer_key( &p2->data, key );
2634                 
2635         if ( key_index == -1 )
2636                 return WERR_NOMEM;
2637         
2638         regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2639                 type, data, real_len );
2640         
2641         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], size => [%d]\n",
2642                 key, value, real_len ));
2643         
2644         return result;
2645 }
2646
2647 /****************************************************************************
2648  ***************************************************************************/
2649  
2650 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value )
2651 {
2652         int             key_index;
2653
2654         if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2655                 return NULL;
2656
2657         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2658                 key, value ));
2659
2660         return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
2661 }
2662
2663 /****************************************************************************
2664  Unpack a list of registry values frem the TDB
2665  ***************************************************************************/
2666  
2667 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
2668 {
2669         int             len = 0;
2670         uint32          type;
2671         pstring         string, valuename, keyname;
2672         char            *str;
2673         int             size;
2674         uint8           *data_p;
2675         REGISTRY_VALUE  *regval_p;
2676         int             key_index;
2677         
2678         /* add the "PrinterDriverData" key first for performance reasons */
2679         
2680         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
2681
2682         /* loop and unpack the rest of the registry values */
2683         
2684         while ( True ) 
2685         {
2686         
2687                 /* check to see if there are any more registry values */
2688                 
2689                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
2690                 if ( !regval_p ) 
2691                         break;
2692
2693                 /* unpack the next regval */
2694                 
2695                 len += tdb_unpack(buf+len, buflen-len, "fdB",
2696                                   string,
2697                                   &type,
2698                                   &size,
2699                                   &data_p);
2700         
2701                 /*
2702                  * break of the keyname from the value name.  
2703                  * Should only be one '\' in the string returned.
2704                  */     
2705                  
2706                 str = strrchr( string, '\\');
2707                 
2708                 /* Put in "PrinterDriverData" is no key specified */
2709                 
2710                 if ( !str ) {
2711                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
2712                         pstrcpy( valuename, string );
2713                 }
2714                 else {
2715                         *str = '\0';
2716                         pstrcpy( keyname, string );
2717                         pstrcpy( valuename, str+1 );
2718                 }
2719                         
2720                 /* see if we need a new key */
2721                 
2722                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
2723                         key_index = add_new_printer_key( printer_data, keyname );
2724                         
2725                 if ( key_index == -1 ) {
2726                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
2727                                 keyname));
2728                         break;
2729                 }
2730                 
2731                 /* add the new value */
2732                 
2733                 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size );
2734
2735                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
2736         }
2737
2738         return len;
2739 }
2740
2741 /****************************************************************************
2742  ***************************************************************************/
2743
2744 static void map_to_os2_driver(fstring drivername)
2745 {
2746         static BOOL initialised=False;
2747         static fstring last_from,last_to;
2748         char *mapfile = lp_os2_driver_map();
2749         char **lines = NULL;
2750         int numlines = 0;
2751         int i;
2752
2753         if (!strlen(drivername))
2754                 return;
2755
2756         if (!*mapfile)
2757                 return;
2758
2759         if (!initialised) {
2760                 *last_from = *last_to = 0;
2761                 initialised = True;
2762         }
2763
2764         if (strequal(drivername,last_from)) {
2765                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2766                 fstrcpy(drivername,last_to);
2767                 return;
2768         }
2769
2770         lines = file_lines_load(mapfile, &numlines);
2771         if (numlines == 0) {
2772                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2773                 return;
2774         }
2775
2776         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2777
2778         for( i = 0; i < numlines; i++) {
2779                 char *nt_name = lines[i];
2780                 char *os2_name = strchr(nt_name,'=');
2781
2782                 if (!os2_name)
2783                         continue;
2784
2785                 *os2_name++ = 0;
2786
2787                 while (isspace(*nt_name))
2788                         nt_name++;
2789
2790                 if (!*nt_name || strchr("#;",*nt_name))
2791                         continue;
2792
2793                 {
2794                         int l = strlen(nt_name);
2795                         while (l && isspace(nt_name[l-1])) {
2796                                 nt_name[l-1] = 0;
2797                                 l--;
2798                         }
2799                 }
2800
2801                 while (isspace(*os2_name))
2802                         os2_name++;
2803
2804                 {
2805                         int l = strlen(os2_name);
2806                         while (l && isspace(os2_name[l-1])) {
2807                                 os2_name[l-1] = 0;
2808                                 l--;
2809                         }
2810                 }
2811
2812                 if (strequal(nt_name,drivername)) {
2813                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2814                         fstrcpy(last_from,drivername);
2815                         fstrcpy(last_to,os2_name);
2816                         fstrcpy(drivername,os2_name);
2817                         file_lines_free(lines);
2818                         return;
2819                 }
2820         }
2821
2822         file_lines_free(lines);
2823 }
2824
2825 /****************************************************************************
2826 get a default printer info 2 struct
2827 ****************************************************************************/
2828 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2829 {
2830         int snum;
2831         NT_PRINTER_INFO_LEVEL_2 info;
2832
2833         ZERO_STRUCT(info);
2834
2835         snum = lp_servicenumber(sharename);
2836
2837         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2838         slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
2839                  get_called_name(), sharename);
2840         fstrcpy(info.sharename, sharename);
2841         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2842         fstrcpy(info.drivername, lp_printerdriver(snum));
2843
2844         /* by setting the driver name to an empty string, a local NT admin
2845            can now run the **local** APW to install a local printer driver
2846            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
2847            installed on the Samba server for NT clients --jerry */
2848 #if 0   /* JERRY --do not uncomment-- */
2849         if (!*info.drivername)
2850                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2851 #endif
2852
2853
2854         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2855
2856         pstrcpy(info.comment, "");
2857         fstrcpy(info.printprocessor, "winprint");
2858         fstrcpy(info.datatype, "RAW");
2859
2860         info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;      /* attributes */
2861
2862         info.starttime = 0; /* Minutes since 12:00am GMT */
2863         info.untiltime = 0; /* Minutes since 12:00am GMT */
2864         info.priority = 1;
2865         info.default_priority = 1;
2866         info.setuptime = (uint32)time(NULL);
2867
2868         /*
2869          * I changed this as I think it is better to have a generic
2870          * DEVMODE than to crash Win2k explorer.exe   --jerry
2871          * See the HP Deskjet 990c Win2k drivers for an example.
2872          *
2873          * However the default devmode appears to cause problems
2874          * with the HP CLJ 8500 PCL driver.  Hence the addition of
2875          * the "default devmode" parameter   --jerry 22/01/2002
2876          */
2877
2878         if (lp_default_devmode(snum)) {
2879                 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2880                         goto fail;
2881         }
2882         else {
2883                 info.devmode = NULL;
2884         }
2885
2886         /* This will get the current RPC talloc context, but we should be
2887            passing this as a parameter... fixme... JRA ! */
2888
2889         if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2890                 goto fail;
2891
2892         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2893         if (! *info_ptr) {
2894                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2895                 goto fail;
2896         }
2897
2898         return WERR_OK;
2899
2900   fail:
2901         if (info.devmode)
2902                 free_nt_devicemode(&info.devmode);
2903         return WERR_ACCESS_DENIED;
2904 }
2905
2906 /****************************************************************************
2907 ****************************************************************************/
2908 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2909 {
2910         pstring key;
2911         NT_PRINTER_INFO_LEVEL_2 info;
2912         int             len = 0;
2913         TDB_DATA kbuf, dbuf;
2914         fstring printername;
2915                 
2916         ZERO_STRUCT(info);
2917
2918         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2919
2920         kbuf.dptr = key;
2921         kbuf.dsize = strlen(key)+1;
2922
2923         dbuf = tdb_fetch(tdb_printers, kbuf);
2924         if (!dbuf.dptr)
2925                 return get_a_printer_2_default(info_ptr, sharename);
2926
2927         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2928                         &info.attributes,
2929                         &info.priority,
2930                         &info.default_priority,
2931                         &info.starttime,
2932                         &info.untiltime,
2933                         &info.status,
2934                         &info.cjobs,
2935                         &info.averageppm,
2936                         &info.changeid,
2937                         &info.c_setprinter,
2938                         &info.setuptime,
2939                         info.servername,
2940                         info.printername,
2941                         info.sharename,
2942                         info.portname,
2943                         info.drivername,
2944                         info.comment,
2945                         info.location,
2946                         info.sepfile,
2947                         info.printprocessor,
2948                         info.datatype,
2949                         info.parameters);
2950
2951         /* Samba has to have shared raw drivers. */
2952         info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK); 
2953
2954         /* Restore the stripped strings. */
2955         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2956         slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2957                         info.printername);
2958         fstrcpy(info.printername, printername);
2959
2960         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2961
2962         /*
2963          * Some client drivers freak out if there is a NULL devmode
2964          * (probably the driver is not checking before accessing 
2965          * the devmode pointer)   --jerry
2966          *
2967          * See comments in get_a_printer_2_default()
2968          */
2969
2970         if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2971         {
2972                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2973                         printername));
2974                 info.devmode = construct_nt_devicemode(printername);
2975         }
2976
2977         len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
2978
2979         /* This will get the current RPC talloc context, but we should be
2980            passing this as a parameter... fixme... JRA ! */
2981
2982         nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2983
2984         /* Fix for OS/2 drivers. */
2985
2986         if (get_remote_arch() == RA_OS2)
2987                 map_to_os2_driver(info.drivername);
2988
2989         SAFE_FREE(dbuf.dptr);
2990         *info_ptr=memdup(&info, sizeof(info));
2991
2992         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2993                  sharename, info.printername, info.drivername));
2994
2995         return WERR_OK; 
2996 }
2997
2998 /****************************************************************************
2999 debugging function, dump at level 6 the struct in the logs
3000 ****************************************************************************/
3001 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3002 {
3003         uint32 result;
3004         NT_PRINTER_INFO_LEVEL_2 *info2;
3005         
3006         DEBUG(106,("Dumping printer at level [%d]\n", level));
3007         
3008         switch (level)
3009         {
3010                 case 2:
3011                 {
3012                         if (printer.info_2 == NULL)
3013                                 result=5;
3014                         else
3015                         {
3016                                 info2=printer.info_2;
3017                         
3018                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3019                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3020                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3021                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3022                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3023                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3024                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3025                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3026                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3027                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3028                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3029
3030                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3031                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3032                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3033                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3034                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3035                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3036                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3037                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3038                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3039                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3040                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3041                                 result=0;
3042                         }
3043                         break;
3044                 }
3045                 default:
3046                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3047                         result=1;
3048                         break;
3049         }
3050         
3051         return result;
3052 }
3053
3054 /****************************************************************************
3055  Get the parameters we can substitute in an NT print job.
3056 ****************************************************************************/
3057
3058 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
3059 {
3060         NT_PRINTER_INFO_LEVEL *printer = NULL;
3061
3062         **printername = **sharename = **portname = '\0';
3063
3064         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3065                 return;
3066
3067         fstrcpy(*printername, printer->info_2->printername);
3068         fstrcpy(*sharename, printer->info_2->sharename);
3069         fstrcpy(*portname, printer->info_2->portname);
3070
3071         free_a_printer(&printer, 2);
3072 }
3073
3074 /****************************************************************************
3075  Update the changeid time.
3076  This is SO NASTY as some drivers need this to change, others need it
3077  static. This value will change every second, and I must hope that this
3078  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3079  UTAH ! JRA.
3080 ****************************************************************************/
3081
3082 static uint32 rev_changeid(void)
3083 {
3084         struct timeval tv;
3085
3086         get_process_uptime(&tv);
3087
3088 #if 1   /* JERRY */
3089         /* Return changeid as msec since spooler restart */
3090         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3091 #else
3092         /*
3093          * This setting seems to work well but is too untested
3094          * to replace the above calculation.  Left in for experiementation
3095          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3096          */
3097         return tv.tv_sec * 10 + tv.tv_usec / 100000;
3098 #endif
3099 }
3100
3101 /*
3102  * The function below are the high level ones.
3103  * only those ones must be called from the spoolss code.
3104  * JFM.
3105  */
3106
3107 /****************************************************************************
3108  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3109 ****************************************************************************/
3110
3111 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3112 {
3113         WERROR result;
3114         
3115         dump_a_printer(printer, level); 
3116         
3117         switch (level)
3118         {
3119                 case 2:
3120                 {
3121                         /*
3122                          * Update the changestamp.  Emperical tests show that the
3123                          * ChangeID is always updated,but c_setprinter is  
3124                          *  global spooler variable (not per printer).
3125                          */
3126
3127                         /* ChangeID **must** be increasing over the lifetime
3128                            of client's spoolss service in order for the
3129                            client's cache to show updates */
3130
3131                         printer.info_2->changeid = rev_changeid();
3132
3133                         /*
3134                          * Because one day someone will ask:
3135                          * NT->NT       An admin connection to a remote
3136                          *              printer show changes imeediately in
3137                          *              the properities dialog
3138                          *      
3139                          *              A non-admin connection will only show the
3140                          *              changes after viewing the properites page
3141                          *              2 times.  Seems to be related to a
3142                          *              race condition in the client between the spooler
3143                          *              updating the local cache and the Explorer.exe GUI
3144                          *              actually displaying the properties.
3145                          *
3146                          *              This is fixed in Win2k.  admin/non-admin
3147                          *              connections both display changes immediately.
3148                          *
3149                          * 14/12/01     --jerry
3150                          */
3151
3152                         result=update_a_printer_2(printer.info_2);
3153                         break;
3154                 }
3155                 default:
3156                         result=WERR_UNKNOWN_LEVEL;
3157                         break;
3158         }
3159         
3160         return result;
3161 }
3162
3163 /****************************************************************************
3164  Initialize printer devmode & data with previously saved driver init values.
3165 ****************************************************************************/
3166
3167 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3168 {
3169         int                     len = 0;
3170         pstring                 key;
3171         TDB_DATA                kbuf, dbuf;
3172         NT_PRINTER_INFO_LEVEL_2 info;
3173
3174
3175         ZERO_STRUCT(info);
3176
3177         /*
3178          * Delete any printer data 'values' already set. When called for driver
3179          * replace, there will generally be some, but during an add printer, there
3180          * should not be any (if there are delete them).
3181          */
3182          
3183         delete_all_printer_data( info_ptr, "" );
3184         
3185         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3186
3187         kbuf.dptr = key;
3188         kbuf.dsize = strlen(key)+1;
3189
3190         dbuf = tdb_fetch(tdb_drivers, kbuf);
3191         if (!dbuf.dptr) {
3192                 /*
3193                  * When changing to a driver that has no init info in the tdb, remove
3194                  * the previous drivers init info and leave the new on blank.
3195                  */
3196                 free_nt_devicemode(&info_ptr->devmode);
3197                 return False;
3198         }
3199         
3200         /*
3201          * Get the saved DEVMODE..
3202          */
3203          
3204         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3205
3206         /*
3207          * The saved DEVMODE contains the devicename from the printer used during
3208          * the initialization save. Change it to reflect the new printer.
3209          */
3210          
3211         if ( info.devmode ) {
3212         ZERO_STRUCT(info.devmode->devicename);
3213         fstrcpy(info.devmode->devicename, info_ptr->printername);
3214         }
3215
3216         /*
3217          * NT/2k does not change out the entire DeviceMode of a printer
3218          * when changing the driver.  Only the driverextra, private, & 
3219          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3220          *
3221          * Later examination revealed that Windows NT/2k does reset the
3222          * the printer's device mode, bit **only** when you change a 
3223          * property of the device mode such as the page orientation.
3224          * --jerry
3225          */
3226
3227
3228         /* Bind the saved DEVMODE to the new the printer */
3229          
3230         free_nt_devicemode(&info_ptr->devmode);
3231         info_ptr->devmode = info.devmode;
3232
3233         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3234                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3235
3236         /* Add the printer data 'values' to the new printer */
3237          
3238         len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3239         
3240
3241         SAFE_FREE(dbuf.dptr);
3242
3243         return True;    
3244 }
3245
3246 /****************************************************************************
3247  Initialize printer devmode & data with previously saved driver init values.
3248  When a printer is created using AddPrinter, the drivername bound to the
3249  printer is used to lookup previously saved driver initialization info, which
3250  is bound to the new printer.
3251 ****************************************************************************/
3252
3253 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3254 {
3255         BOOL result = False;
3256         
3257         switch (level)
3258         {
3259                 case 2:
3260                         result = set_driver_init_2(printer->info_2);
3261                         break;
3262                         
3263                 default:
3264                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
3265                                 level));
3266                         break;
3267         }
3268         
3269         return result;
3270 }
3271
3272 /****************************************************************************
3273  Delete driver init data stored for a specified driver
3274 ****************************************************************************/
3275
3276 BOOL del_driver_init(char *drivername)
3277 {
3278         pstring key;
3279         TDB_DATA kbuf;
3280
3281         if (!drivername || !*drivername) {
3282                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3283                 return False;
3284         }
3285
3286         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3287
3288         kbuf.dptr = key;
3289         kbuf.dsize = strlen(key)+1;
3290
3291         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3292
3293         return (tdb_delete(tdb_drivers, kbuf) == 0);
3294 }
3295
3296 /****************************************************************************
3297  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
3298  in the tdb. Note: this is different from the driver entry and the printer
3299  entry. There should be a single driver init entry for each driver regardless
3300  of whether it was installed from NT or 2K. Technically, they should be
3301  different, but they work out to the same struct.
3302 ****************************************************************************/
3303
3304 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3305 {
3306         pstring key;
3307         char *buf;
3308         int buflen, len, ret;
3309         TDB_DATA kbuf, dbuf;
3310
3311         buf = NULL;
3312         buflen = 0;
3313
3314  again: 
3315         len = 0;
3316         len += pack_devicemode(info->devmode, buf+len, buflen-len);
3317
3318         len += pack_values( &info->data, buf+len, buflen-len );
3319
3320         if (buflen != len) {
3321                 char *tb;
3322
3323                 tb = (char *)Realloc(buf, len);
3324                 if (!tb) {
3325                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3326                         ret = -1;
3327                         goto done;
3328                 }
3329                 else buf = tb;
3330                 buflen = len;
3331                 goto again;
3332         }
3333
3334         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3335
3336         kbuf.dptr = key;
3337         kbuf.dsize = strlen(key)+1;
3338         dbuf.dptr = buf;
3339         dbuf.dsize = len;
3340
3341         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3342
3343 done:
3344         if (ret == -1)
3345                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3346
3347         SAFE_FREE(buf);
3348
3349         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3350                  info->sharename, info->drivername));
3351
3352         return ret;
3353 }
3354
3355 /****************************************************************************
3356  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3357 ****************************************************************************/
3358
3359 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3360 {
3361         uint32 result;
3362         
3363         dump_a_printer(printer, level); 
3364         
3365         switch (level)
3366         {
3367                 case 2:
3368                 {
3369                         result = update_driver_init_2(printer.info_2);
3370                         break;
3371                 }
3372                 default:
3373                         result = 1;
3374                         break;
3375         }
3376         
3377         return result;
3378 }
3379
3380 /****************************************************************************
3381  Convert the printer data value, a REG_BINARY array, into an initialization 
3382  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3383  got to keep the endians happy :).
3384 ****************************************************************************/
3385
3386 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3387 {
3388         BOOL       result = False;
3389         prs_struct ps;
3390         DEVICEMODE devmode;
3391
3392         ZERO_STRUCT(devmode);
3393
3394         prs_init(&ps, 0, ctx, UNMARSHALL);
3395         ps.data_p      = (char *)data;
3396         ps.buffer_size = data_len;
3397
3398         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3399                 result = convert_devicemode("", &devmode, &nt_devmode);
3400         else
3401                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3402
3403         return result;
3404 }
3405
3406 /****************************************************************************
3407  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3408
3409  1. Use the driver's config DLL to this UNC printername and:
3410     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3411     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3412  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3413
3414  The last step triggers saving the "driver initialization" information for
3415  this printer into the tdb. Later, new printers that use this driver will
3416  have this initialization information bound to them. This simulates the
3417  driver initialization, as if it had run on the Samba server (as it would
3418  have done on NT).
3419
3420  The Win32 client side code requirement sucks! But until we can run arbitrary
3421  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3422  
3423  It would have been easier to use SetPrinter because all the UNMARSHALLING of
3424  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3425  about it and you will realize why.  JRR 010720
3426 ****************************************************************************/
3427
3428 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3429 {
3430         WERROR        status       = WERR_OK;
3431         TALLOC_CTX    *ctx         = NULL;
3432         NT_DEVICEMODE *nt_devmode  = NULL;
3433         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3434         
3435         /*
3436          * When the DEVMODE is already set on the printer, don't try to unpack it.
3437          */
3438         DEBUG(8,("save_driver_init_2: Enter...\n"));
3439         
3440         if ( !printer->info_2->devmode && data_len ) 
3441         {
3442                 /*
3443                  * Set devmode on printer info, so entire printer initialization can be
3444                  * saved to tdb.
3445                  */
3446
3447                 if ((ctx = talloc_init()) == NULL)
3448                         return WERR_NOMEM;
3449
3450                 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3451                         status = WERR_NOMEM;
3452                         goto done;
3453                 }
3454         
3455                 ZERO_STRUCTP(nt_devmode);
3456
3457                 /*
3458                  * The DEVMODE is held in the 'data' component of the param in raw binary.
3459                  * Convert it to to a devmode structure
3460                  */
3461                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3462                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3463                         status = WERR_INVALID_PARAM;
3464                         goto done;
3465                 }
3466
3467                 printer->info_2->devmode = nt_devmode;
3468         }
3469
3470         /*
3471          * Pack up and add (or update) the DEVMODE and any current printer data to
3472          * a 'driver init' element in the tdb
3473          * 
3474          */
3475
3476         if ( update_driver_init(*printer, 2) != 0 ) {
3477                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3478                 status = WERR_NOMEM;
3479                 goto done;
3480         }
3481         
3482         /*
3483          * If driver initialization info was successfully saved, set the current 
3484          * printer to match it. This allows initialization of the current printer 
3485          * as well as the driver.
3486          */
3487         status = mod_a_printer(*printer, 2);
3488         if (!W_ERROR_IS_OK(status)) {
3489                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3490                                   printer->info_2->printername));
3491         }
3492         
3493   done:
3494         talloc_destroy(ctx);
3495         free_nt_devicemode( &nt_devmode );
3496         
3497         printer->info_2->devmode = tmp_devmode;
3498
3499         return status;
3500 }
3501
3502 /****************************************************************************
3503  Update the driver init info (DEVMODE and specifics) for a printer
3504 ****************************************************************************/
3505
3506 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3507 {
3508         WERROR status = WERR_OK;
3509         
3510         switch (level)
3511         {
3512                 case 2:
3513                 {
3514                         status = save_driver_init_2( printer, data, data_len );
3515                         break;
3516                 }
3517                 default:
3518                         status = WERR_UNKNOWN_LEVEL;
3519                         break;
3520         }
3521         
3522         return status;
3523 }
3524
3525 /****************************************************************************
3526  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3527 ****************************************************************************/
3528
3529 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3530 {
3531         WERROR result;
3532         NT_PRINTER_INFO_LEVEL *printer = NULL;
3533         
3534         *pp_printer = NULL;
3535
3536         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3537
3538         switch (level)
3539         {
3540                 case 2:
3541                 {
3542                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3543                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
3544                                 return WERR_NOMEM;
3545                         }
3546                         ZERO_STRUCTP(printer);
3547                         result=get_a_printer_2(&printer->info_2, sharename);
3548                         if (W_ERROR_IS_OK(result)) {
3549                                 dump_a_printer(*printer, level);
3550                                 *pp_printer = printer;
3551                         } else {
3552                                 SAFE_FREE(printer);
3553                         }
3554                         break;
3555                 }
3556                 default:
3557                         result=WERR_UNKNOWN_LEVEL;
3558                         break;
3559         }
3560         
3561         DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3562
3563         return result;
3564 }
3565
3566 /****************************************************************************
3567  Deletes a NT_PRINTER_INFO_LEVEL struct.
3568 ****************************************************************************/
3569
3570 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3571 {
3572         uint32 result;
3573         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3574
3575         DEBUG(104,("freeing a printer at level [%d]\n", level));
3576
3577         if (printer == NULL)
3578                 return 0;
3579         
3580         switch (level)
3581         {
3582                 case 2:
3583                 {
3584                         if (printer->info_2 != NULL)
3585                         {
3586                                 free_nt_printer_info_level_2(&printer->info_2);
3587                                 result=0;
3588                         }
3589                         else
3590                         {
3591                                 result=4;
3592                         }
3593                         break;
3594                 }
3595                 default:
3596                         result=1;
3597                         break;
3598         }
3599
3600         SAFE_FREE(*pp_printer);
3601         return result;
3602 }
3603
3604 /****************************************************************************
3605 ****************************************************************************/
3606 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3607 {
3608         uint32 result;
3609         DEBUG(104,("adding a printer at level [%d]\n", level));
3610         dump_a_printer_driver(driver, level);
3611         
3612         switch (level)
3613         {
3614                 case 3:
3615                 {
3616                         result=add_a_printer_driver_3(driver.info_3);
3617                         break;
3618                 }
3619
3620                 case 6:
3621                 {
3622                         result=add_a_printer_driver_6(driver.info_6);
3623                         break;
3624                 }
3625                 default:
3626                         result=1;
3627                         break;
3628         }
3629         
3630         return result;
3631 }
3632 /****************************************************************************
3633 ****************************************************************************/
3634 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3635                             fstring drivername, fstring architecture, uint32 version)
3636 {
3637         WERROR result;
3638         
3639         switch (level)
3640         {
3641                 case 3:
3642                         /* Sometime we just want any version of the driver */
3643                         
3644                         if ( version == DRIVER_ANY_VERSION ) {
3645                                 /* look for Win2k first and then for NT4 */
3646                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
3647                                                 architecture, 3);
3648                                                 
3649                                 if ( !W_ERROR_IS_OK(result) ) {
3650                                         result = get_a_printer_driver_3( &driver->info_3, 
3651                                                         drivername, architecture, 2 );
3652                                 }
3653                         }
3654                         else {
3655                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
3656                                         architecture, version);                         
3657                         }
3658                         break;
3659                         
3660                 default:
3661                         result=W_ERROR(1);
3662                         break;
3663         }
3664         
3665         if (W_ERROR_IS_OK(result))
3666                 dump_a_printer_driver(*driver, level);
3667                 
3668         return result;
3669 }
3670
3671 /****************************************************************************
3672 ****************************************************************************/
3673 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3674 {
3675         uint32 result;
3676         
3677         switch (level)
3678         {
3679                 case 3:
3680                 {
3681                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3682                         if (driver.info_3 != NULL)
3683                         {
3684                                 info3=driver.info_3;
3685                                 SAFE_FREE(info3->dependentfiles);
3686                                 ZERO_STRUCTP(info3);
3687                                 SAFE_FREE(info3);
3688                                 result=0;
3689                         }
3690                         else
3691                         {
3692                                 result=4;
3693                         }
3694                         break;
3695                 }
3696                 case 6:
3697                 {
3698                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3699                         if (driver.info_6 != NULL)
3700                         {
3701                                 info6=driver.info_6;
3702                                 SAFE_FREE(info6->dependentfiles);
3703                                 SAFE_FREE(info6->previousnames);
3704                                 ZERO_STRUCTP(info6);
3705                                 SAFE_FREE(info6);
3706                                 result=0;
3707                         }
3708                         else
3709                         {
3710                                 result=4;
3711                         }
3712                         break;
3713                 }
3714                 default:
3715                         result=1;
3716                         break;
3717         }
3718         return result;
3719 }
3720
3721
3722 /****************************************************************************
3723   Determine whether or not a particular driver is currently assigned
3724   to a printer
3725 ****************************************************************************/
3726
3727 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
3728 {
3729         int snum;
3730         int n_services = lp_numservices();
3731         NT_PRINTER_INFO_LEVEL *printer = NULL;
3732
3733         if ( !i ) 
3734                 return False;
3735
3736         DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3737         
3738         /* loop through the printers.tdb and check for the drivername */
3739         
3740         for (snum=0; snum<n_services; snum++) 
3741         {
3742                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
3743                         continue;
3744                 
3745                 if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
3746                         continue;
3747                 
3748                 if ( !StrCaseCmp(i->name, printer->info_2->drivername) ) {
3749                         free_a_printer( &printer, 2 );
3750                         return True;
3751                 }
3752                 
3753                 free_a_printer( &printer, 2 );
3754         }
3755         
3756         DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3757         
3758         /* report that the driver is not in use by default */
3759         
3760         return False;
3761 }
3762
3763
3764 /**********************************************************************
3765  Check to see if a ogiven file is in use by *info
3766  *********************************************************************/
3767  
3768 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3769 {
3770         char *s;
3771         
3772         if ( !info )
3773                 return False;
3774                 
3775         if ( strequal(file, info->driverpath) )
3776                 return True;
3777
3778         if ( strequal(file, info->datafile) )
3779                 return True;
3780
3781         if ( strequal(file, info->configfile) )
3782                 return True;
3783
3784         if ( strequal(file, info->helpfile) )
3785                 return True;
3786                 
3787         s = (char*) info->dependentfiles;
3788         
3789         if ( s ) {
3790                 while ( *s )
3791                 {
3792                         if ( strequal(file, s) )
3793                                 return True;
3794                         s += strlen(s) + 1;
3795                 }
3796         }
3797         
3798         return False;
3799
3800 }
3801
3802 /**********************************************************************
3803  Utility function to remove the dependent file pointed to by the 
3804  input parameter from the list 
3805  *********************************************************************/
3806
3807 static void trim_dependent_file( char* s )
3808 {
3809         char *p;
3810         
3811         /* set p to the next character string in the list */
3812         
3813         p = s + strlen( s ) + 1;
3814         
3815         /* check to see that we have another string to copy back */
3816         
3817         if ( *p == '\0' ) 
3818         {
3819                 /* loop over s copying characters from p to s */
3820                 while ( *p!='\0' && *(p+1)!='\0' )
3821                         *s++ = *p++;
3822         }
3823         
3824         /* add the two trailing NULL's */
3825         
3826         *s      = '\0';
3827         *(s+1)  = '\0';
3828 }
3829
3830 /**********************************************************************
3831  Check if any of the files used by src are also used by drv 
3832  *********************************************************************/
3833
3834 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
3835                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
3836 {
3837         BOOL in_use = False;
3838         char *s;
3839         
3840         if ( !src || !drv )
3841                 return False;
3842                 
3843         /* check each file.  Remove it from the src structure if it overlaps */
3844         
3845         if ( drv_file_in_use(src->driverpath, drv) ) {
3846                 in_use = True;
3847                 fstrcpy( src->driverpath, "" );
3848         }
3849                 
3850         if ( drv_file_in_use(src->datafile, drv) ) {
3851                 in_use = True;
3852                 fstrcpy( src->datafile, "" );
3853         }
3854                 
3855         if ( drv_file_in_use(src->configfile, drv) ) {
3856                 in_use = True;
3857                 fstrcpy( src->configfile, "" );
3858         }
3859                 
3860         s = (char*)src->dependentfiles;
3861         
3862         if ( s ) {
3863                 while ( *s ) 
3864                 {
3865                         if ( drv_file_in_use(s, drv) ) {
3866                                 in_use = True;
3867                                 trim_dependent_file( s );
3868                         }
3869                         else
3870                                 s += strlen(s) + 1;     
3871                 } 
3872         }
3873                 
3874                 
3875         return in_use;
3876 }
3877
3878 /****************************************************************************
3879   Determine whether or not a particular driver files are currently being 
3880   used by any other driver.  
3881   
3882   Return value is True if any files were in use by other drivers
3883   and False otherwise.
3884   
3885   Upon return, *info has been modified to only contain the driver files
3886   which are not in use
3887 ****************************************************************************/
3888
3889 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3890 {
3891         int                             i;
3892         int                             ndrivers;
3893         uint32                          version;
3894         fstring                         *list = NULL;
3895         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
3896         
3897         /* loop over all driver versions */
3898         
3899         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
3900         
3901         for ( version=0; version<DRIVER_MAX_VERSION; version++ )
3902         {
3903                 /* get the list of drivers */
3904                 
3905                 list = NULL;
3906                 ndrivers = get_ntdrivers(&list, info->environment, version);
3907                 
3908                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
3909                         ndrivers, info->environment, version));
3910
3911                 if (ndrivers == -1)
3912                         continue;
3913                         
3914                 /* check each driver for overlap in files */
3915                 
3916                 for (i=0; i<ndrivers; i++) 
3917                 {
3918                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3919                         
3920                         ZERO_STRUCT(driver);
3921                         
3922                         if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], 
3923                                 info->environment, version)) )
3924                         {
3925                                 SAFE_FREE(list);
3926                                 return True;
3927                         }
3928                         
3929                         /* check if d2 uses any files from d1 */
3930                         /* only if this is a different driver than the one being deleted */
3931                         
3932                         if ( !strequal(info->name, driver.info_3->name) 
3933                                 || (info->cversion != driver.info_3->cversion) )
3934                         {
3935                                 if ( trim_overlap_drv_files(info, driver.info_3) ) {
3936                                         free_a_printer_driver(driver, 3);
3937                                         SAFE_FREE( list );
3938                                         return True;
3939                                 }
3940                         }
3941         
3942                         free_a_printer_driver(driver, 3);
3943                 }       
3944                 
3945                 SAFE_FREE(list);
3946         }
3947         
3948         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
3949         
3950         return False;
3951 }
3952
3953 /****************************************************************************
3954   Actually delete the driver files.  Make sure that 
3955   printer_driver_files_in_use() return False before calling 
3956   this.
3957 ****************************************************************************/
3958
3959 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user )
3960 {
3961         char *s;
3962         connection_struct *conn;
3963         DATA_BLOB null_pw;
3964         NTSTATUS nt_status;
3965         
3966         if ( !i )
3967                 return False;
3968                 
3969         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->cversion));
3970         
3971         /*
3972          * Connect to the print$ share under the same account as the 
3973          * user connected to the rpc pipe. Note we must be root to 
3974          * do this.
3975          */
3976          
3977         become_root();
3978         null_pw = data_blob( NULL, 0 );
3979         conn = make_connection_with_chdir( "print$", null_pw, "A:", user->vuid, &nt_status );
3980         unbecome_root();
3981         
3982         if ( !conn ) {
3983                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
3984                 return False;
3985         }
3986
3987         /* Save who we are - we are temporarily becoming the connection user. */
3988
3989         if ( !become_user(conn, conn->vuid) ) {
3990                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
3991                 return False;
3992         }
3993
3994         /* now delete the files; must strip the '\print$' string from 
3995            fron of path                                                */
3996         
3997         if ( *i->driverpath ) {
3998                 if ( (s = strchr( &i->driverpath[1], '\\' )) != NULL ) {
3999                         DEBUG(10,("deleting driverfile [%s]\n", s));
4000                         unlink_internals(conn, 0, s);
4001                 }
4002         }
4003                 
4004         if ( *i->configfile ) {
4005                 if ( (s = strchr( &i->configfile[1], '\\' )) != NULL ) {
4006                         DEBUG(10,("deleting configfile [%s]\n", s));
4007                         unlink_internals(conn, 0, s);
4008                 }
4009         }
4010         
4011         if ( *i->datafile ) {
4012                 if ( (s = strchr( &i->datafile[1], '\\' )) != NULL ) {
4013                         DEBUG(10,("deleting datafile [%s]\n", s));
4014                         unlink_internals(conn, 0, s);
4015                 }
4016         }
4017         
4018         if ( *i->helpfile ) {
4019                 if ( (s = strchr( &i->helpfile[1], '\\' )) != NULL ) {
4020                         DEBUG(10,("deleting helpfile [%s]\n", s));
4021                         unlink_internals(conn, 0, s);
4022                 }
4023         }
4024         
4025         s = (char*)i->dependentfiles;
4026         
4027         while ( s && *s ) {
4028                 char *file;
4029
4030                 if ( (file = strchr( s+1, '\\' )) != NULL )
4031                 {
4032                         DEBUG(10,("deleting dependent file [%s]\n", file));
4033                         unlink_internals(conn, 0, file );
4034                         file += strlen( file ) + 1;
4035                 }
4036
4037                 s = file;
4038         }
4039
4040         return True;
4041 }
4042
4043 /****************************************************************************
4044  Remove a printer driver from the TDB.  This assumes that the the driver was
4045  previously looked up.
4046  ***************************************************************************/
4047
4048 static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
4049                               uint32 version, BOOL delete_files )
4050 {
4051         pstring         key;
4052         fstring         arch;
4053         TDB_DATA        kbuf, dbuf;
4054         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4055
4056         /* delete the tdb data first */
4057
4058         get_short_archi(arch, i->environment);
4059         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4060                 arch, version, i->name);
4061
4062         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4063                 key, delete_files ? "TRUE" : "FALSE" ));
4064
4065         ctr.info_3 = i;
4066         dump_a_printer_driver( ctr, 3 );
4067
4068         kbuf.dptr=key;
4069         kbuf.dsize=strlen(key)+1;
4070
4071         /* check if the driver actually exists for this environment */
4072         
4073         dbuf = tdb_fetch( tdb_drivers, kbuf );
4074         if ( !dbuf.dptr ) {
4075                 DEBUG(8,("delete_printer_driver_internal: Driver unknown [%s]\n", key));
4076                 return WERR_UNKNOWN_PRINTER_DRIVER;
4077         }
4078                 
4079         SAFE_FREE( dbuf.dptr );
4080         
4081         /* ok... the driver exists so the delete should return success */
4082                 
4083         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4084                 DEBUG (0,("delete_printer_driver_internal: fail to delete %s!\n", key));
4085                 return WERR_ACCESS_DENIED;
4086         }
4087
4088         /*
4089          * now delete any associated files if delete_files == True
4090          * even if this part failes, we return succes because the
4091          * driver doesn not exist any more
4092          */
4093
4094         if ( delete_files )
4095                 delete_driver_files( i, user );
4096
4097
4098         DEBUG(5,("delete_printer_driver_internal: driver delete successful [%s]\n", key));
4099
4100         return WERR_OK;
4101 }
4102
4103 /****************************************************************************
4104  Remove a printer driver from the TDB.  This assumes that the the driver was
4105  previously looked up.
4106  ***************************************************************************/
4107
4108 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
4109                               uint32 version, BOOL delete_files )
4110 {
4111         WERROR err;
4112
4113         /*
4114          * see if we should delete all versions of this driver 
4115          * (DRIVER_ANY_VERSION uis only set for "Windows NT x86")
4116          */
4117
4118         if ( version == DRIVER_ANY_VERSION ) 
4119         {
4120                 /* Windows NT 4.0 */
4121                 
4122                 err = delete_printer_driver_internal(i, user, 2, delete_files );
4123                 if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) )
4124                         return err;
4125                         
4126                 /* Windows 2000/XP  */
4127                 
4128                 err = delete_printer_driver_internal(i, user, 3, delete_files );
4129                 if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) )
4130                                 return err;
4131
4132         return WERR_OK;
4133         }
4134         
4135         /* just delete what they asked for */
4136         
4137         return delete_printer_driver_internal(i, user, version, delete_files );
4138 }
4139
4140 /****************************************************************************
4141  Store a security desc for a printer.
4142 ****************************************************************************/
4143
4144 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4145 {
4146         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4147         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4148         prs_struct ps;
4149         TALLOC_CTX *mem_ctx = NULL;
4150         fstring key;
4151         WERROR status;
4152
4153         mem_ctx = talloc_init();
4154         if (mem_ctx == NULL)
4155                 return WERR_NOMEM;
4156
4157         /* The old owner and group sids of the security descriptor are not
4158            present when new ACEs are added or removed by changing printer
4159            permissions through NT.  If they are NULL in the new security
4160            descriptor then copy them over from the old one. */
4161
4162         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4163                 DOM_SID *owner_sid, *group_sid;
4164                 SEC_ACL *dacl, *sacl;
4165                 SEC_DESC *psd = NULL;
4166                 size_t size;
4167
4168                 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4169
4170                 /* Pick out correct owner and group sids */
4171
4172                 owner_sid = secdesc_ctr->sec->owner_sid ?
4173                         secdesc_ctr->sec->owner_sid :
4174                         old_secdesc_ctr->sec->owner_sid;
4175
4176                 group_sid = secdesc_ctr->sec->grp_sid ?
4177                         secdesc_ctr->sec->grp_sid :
4178                         old_secdesc_ctr->sec->grp_sid;
4179
4180                 dacl = secdesc_ctr->sec->dacl ?
4181                         secdesc_ctr->sec->dacl :
4182                         old_secdesc_ctr->sec->dacl;
4183
4184                 sacl = secdesc_ctr->sec->sacl ?
4185                         secdesc_ctr->sec->sacl :
4186                         old_secdesc_ctr->sec->sacl;
4187
4188                 /* Make a deep copy of the security descriptor */
4189
4190                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
4191                                     owner_sid, group_sid,
4192                                     sacl,
4193                                     dacl,
4194                                     &size);
4195
4196                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4197         }
4198
4199         if (!new_secdesc_ctr) {
4200                 new_secdesc_ctr = secdesc_ctr;
4201         }
4202
4203         /* Store the security descriptor in a tdb */
4204
4205         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4206                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4207
4208         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4209                              &ps, 1)) {
4210                 status = WERR_BADFUNC;
4211                 goto out;
4212         }
4213
4214         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4215
4216         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4217                 status = WERR_OK;
4218         } else {
4219                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4220                 status = WERR_BADFUNC;
4221         }
4222
4223         /* Free malloc'ed memory */
4224
4225  out:
4226
4227         prs_mem_free(&ps);
4228         if (mem_ctx)
4229                 talloc_destroy(mem_ctx);
4230         return status;
4231 }
4232
4233 /****************************************************************************
4234  Construct a default security descriptor buffer for a printer.
4235 ****************************************************************************/
4236
4237 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4238 {
4239         SEC_ACE ace[3];
4240         SEC_ACCESS sa;
4241         SEC_ACL *psa = NULL;
4242         SEC_DESC_BUF *sdb = NULL;
4243         SEC_DESC *psd = NULL;
4244         DOM_SID owner_sid;
4245         size_t sd_size;
4246
4247         /* Create an ACE where Everyone is allowed to print */
4248
4249         init_sec_access(&sa, PRINTER_ACE_PRINT);
4250         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4251                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4252
4253         /* Make the security descriptor owned by the Administrators group
4254            on the PDC of the domain. */
4255
4256         if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4257                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4258         } else {
4259
4260                 /* Backup plan - make printer owned by admins.
4261                    This should emulate a lanman printer as security
4262                    settings can't be changed. */
4263
4264                 sid_copy(&owner_sid, get_global_sam_sid());
4265                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4266         }
4267
4268         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4269         init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4270                      sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4271                      SEC_ACE_FLAG_INHERIT_ONLY);
4272
4273         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4274         init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4275                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4276
4277         /* The ACL revision number in rpc_secdesc.h differs from the one
4278            created by NT when setting ACE entries in printer
4279            descriptors.  NT4 complains about the property being edited by a
4280            NT5 machine. */
4281
4282         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4283                 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4284                                     &owner_sid, NULL,
4285                                     NULL, psa, &sd_size);
4286         }
4287
4288         if (!psd) {
4289                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4290                 return NULL;
4291         }
4292
4293         sdb = make_sec_desc_buf(ctx, sd_size, psd);
4294
4295         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4296                  (unsigned int)sd_size));
4297
4298         return sdb;
4299 }
4300
4301 /****************************************************************************
4302  Get a security desc for a printer.
4303 ****************************************************************************/
4304
4305 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4306 {
4307         prs_struct ps;
4308         fstring key;
4309         char *temp;
4310
4311         if ((temp = strchr(printername + 2, '\\'))) {
4312                 printername = temp + 1;
4313         }
4314
4315         /* Fetch security descriptor from tdb */
4316
4317         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4318
4319         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4320             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4321
4322                 DEBUG(4,("using default secdesc for %s\n", printername));
4323
4324                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4325                         return False;
4326                 }
4327
4328                 /* Save default security descriptor for later */
4329
4330                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4331                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4332
4333                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4334                         tdb_prs_store(tdb_printers, key, &ps);
4335
4336                 prs_mem_free(&ps);
4337
4338                 return True;
4339         }
4340
4341         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4342            this security descriptor has been created when winbindd was
4343            down.  Take ownership of security descriptor. */
4344
4345         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4346                 DOM_SID owner_sid;
4347
4348                 /* Change sd owner to workgroup administrator */
4349
4350                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4351                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4352                         SEC_DESC *psd = NULL;
4353                         size_t size;
4354
4355                         /* Create new sd */
4356
4357                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4358
4359                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4360                                             &owner_sid,
4361                                             (*secdesc_ctr)->sec->grp_sid,
4362                                             (*secdesc_ctr)->sec->sacl,
4363                                             (*secdesc_ctr)->sec->dacl,
4364                                             &size);
4365
4366                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4367
4368                         /* Swap with other one */
4369
4370                         *secdesc_ctr = new_secdesc_ctr;
4371
4372                         /* Set it */
4373
4374                         nt_printing_setsec(printername, *secdesc_ctr);
4375                 }
4376         }
4377
4378         if (DEBUGLEVEL >= 10) {
4379                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4380                 int i;
4381
4382                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4383                            printername, the_acl->num_aces));
4384
4385                 for (i = 0; i < the_acl->num_aces; i++) {
4386                         fstring sid_str;
4387
4388                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4389
4390                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4391                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
4392                                    the_acl->ace[i].info.mask)); 
4393                 }
4394         }
4395
4396         prs_mem_free(&ps);
4397         return True;
4398 }
4399
4400 /* error code:
4401         0: everything OK
4402         1: level not implemented
4403         2: file doesn't exist
4404         3: can't allocate memory
4405         4: can't free memory
4406         5: non existant struct
4407 */
4408
4409 /*
4410         A printer and a printer driver are 2 different things.
4411         NT manages them separatelly, Samba does the same.
4412         Why ? Simply because it's easier and it makes sense !
4413         
4414         Now explanation: You have 3 printers behind your samba server,
4415         2 of them are the same make and model (laser A and B). But laser B
4416         has an 3000 sheet feeder and laser A doesn't such an option.
4417         Your third printer is an old dot-matrix model for the accounting :-).
4418         
4419         If the /usr/local/samba/lib directory (default dir), you will have
4420         5 files to describe all of this.
4421         
4422         3 files for the printers (1 by printer):
4423                 NTprinter_laser A
4424                 NTprinter_laser B
4425                 NTprinter_accounting
4426         2 files for the drivers (1 for the laser and 1 for the dot matrix)
4427                 NTdriver_printer model X
4428                 NTdriver_printer model Y
4429
4430 jfm: I should use this comment for the text file to explain
4431         same thing for the forms BTW.
4432         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4433
4434 */
4435
4436 /* Convert generic access rights to printer object specific access rights.
4437    It turns out that NT4 security descriptors use generic access rights and
4438    NT5 the object specific ones. */
4439
4440 void map_printer_permissions(SEC_DESC *sd)
4441 {
4442         int i;
4443
4444         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4445                 se_map_generic(&sd->dacl->ace[i].info.mask,
4446                                &printer_generic_mapping);
4447         }
4448 }
4449
4450 /****************************************************************************
4451  Check a user has permissions to perform the given operation.  We use the
4452  permission constants defined in include/rpc_spoolss.h to check the various
4453  actions we perform when checking printer access.
4454
4455    PRINTER_ACCESS_ADMINISTER:
4456        print_queue_pause, print_queue_resume, update_printer_sec,
4457        update_printer, spoolss_addprinterex_level_2,
4458        _spoolss_setprinterdata
4459
4460    PRINTER_ACCESS_USE:
4461        print_job_start
4462
4463    JOB_ACCESS_ADMINISTER:
4464        print_job_delete, print_job_pause, print_job_resume,
4465        print_queue_purge
4466
4467  ****************************************************************************/
4468 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4469 {
4470         SEC_DESC_BUF *secdesc = NULL;
4471         uint32 access_granted;
4472         NTSTATUS status;
4473         BOOL result;
4474         const char *pname;
4475         TALLOC_CTX *mem_ctx = NULL;
4476         extern struct current_user current_user;
4477         
4478         /* If user is NULL then use the current_user structure */
4479
4480         if (!user)
4481                 user = &current_user;
4482
4483         /* Always allow root or printer admins to do anything */
4484
4485         if (user->uid == 0 ||
4486             user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
4487                 return True;
4488         }
4489
4490         /* Get printer name */
4491
4492         pname = PRINTERNAME(snum);
4493
4494         if (!pname || !*pname) {
4495                 errno = EACCES;
4496                 return False;
4497         }
4498
4499         /* Get printer security descriptor */
4500
4501         if(!(mem_ctx = talloc_init())) {
4502                 errno = ENOMEM;
4503                 return False;
4504         }
4505
4506         nt_printing_getsec(mem_ctx, pname, &secdesc);
4507
4508         if (access_type == JOB_ACCESS_ADMINISTER) {
4509                 SEC_DESC_BUF *parent_secdesc = secdesc;
4510
4511                 /* Create a child security descriptor to check permissions
4512                    against.  This is because print jobs are child objects
4513                    objects of a printer. */
4514
4515                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4516
4517                 /* Now this is the bit that really confuses me.  The access
4518                    type needs to be changed from JOB_ACCESS_ADMINISTER to
4519                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
4520                    to do with the child (job) object becoming like a
4521                    printer??  -tpot */
4522
4523                 access_type = PRINTER_ACCESS_ADMINISTER;
4524         }
4525         
4526         /* Check access */
4527         
4528         map_printer_permissions(secdesc->sec);
4529
4530         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4531                                  &access_granted, &status);
4532
4533         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4534
4535         talloc_destroy(mem_ctx);
4536         
4537         if (!result)
4538                 errno = EACCES;
4539
4540         return result;
4541 }
4542
4543 /****************************************************************************
4544  Check the time parameters allow a print operation.
4545 *****************************************************************************/
4546
4547 BOOL print_time_access_check(int snum)
4548 {
4549         NT_PRINTER_INFO_LEVEL *printer = NULL;
4550         BOOL ok = False;
4551         time_t now = time(NULL);
4552         struct tm *t;
4553         uint32 mins;
4554
4555         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4556                 return False;
4557
4558         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4559                 ok = True;
4560
4561         t = gmtime(&now);
4562         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4563
4564         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4565                 ok = True;
4566
4567         free_a_printer(&printer, 2);
4568
4569         if (!ok)
4570                 errno = EACCES;
4571
4572         return ok;
4573 }
4574