sync'ing up for 3.0alpha20 release
[kai/samba.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                     2002.
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_UNKNOWN_PRINTER_DRIVER;
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(20,("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 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 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], type=> [%d], size => [%d]\n",
2642                 key, value, type, 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 *info_3 )
3728 {
3729         int snum;
3730         int n_services = lp_numservices();
3731         NT_PRINTER_INFO_LEVEL *printer = NULL;
3732
3733         if ( !info_3 ) 
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(info_3->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         int i = 0;
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         /* see of there are any dependent files to examine */
3788         
3789         if ( !info->dependentfiles )
3790                 return False;
3791         
3792         while ( *info->dependentfiles[i] ) 
3793         {
3794                 if ( strequal(file, info->dependentfiles[i]) )
3795                         return True;
3796                         
3797                 i++;
3798         }
3799         
3800         return False;
3801
3802 }
3803
3804 /**********************************************************************
3805  Utility function to remove the dependent file pointed to by the 
3806  input parameter from the list 
3807  *********************************************************************/
3808
3809 static void trim_dependent_file( fstring files[], int idx )
3810 {
3811         
3812         /* bump everything down a slot */
3813
3814         while( *files[idx+1] ) 
3815         {
3816                 fstrcpy( files[idx], files[idx+1] );
3817                 idx++;
3818         }
3819         
3820         *files[idx] = '\0';
3821
3822         return; 
3823 }
3824
3825 /**********************************************************************
3826  Check if any of the files used by src are also used by drv 
3827  *********************************************************************/
3828
3829 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
3830                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
3831 {
3832         BOOL    in_use = False;
3833         int     i = 0;
3834         
3835         if ( !src || !drv )
3836                 return False;
3837                 
3838         /* check each file.  Remove it from the src structure if it overlaps */
3839         
3840         if ( drv_file_in_use(src->driverpath, drv) ) {
3841                 in_use = True;
3842                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
3843                 fstrcpy( src->driverpath, "" );
3844         }
3845                 
3846         if ( drv_file_in_use(src->datafile, drv) ) {
3847                 in_use = True;
3848                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
3849                 fstrcpy( src->datafile, "" );
3850         }
3851                 
3852         if ( drv_file_in_use(src->configfile, drv) ) {
3853                 in_use = True;
3854                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
3855                 fstrcpy( src->configfile, "" );
3856         }
3857                 
3858         if ( drv_file_in_use(src->helpfile, drv) ) {
3859                 in_use = True;
3860                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
3861                 fstrcpy( src->helpfile, "" );
3862         }
3863         
3864         /* are there any dependentfiles to examine? */
3865         
3866         if ( !src->dependentfiles )
3867                 return in_use;
3868                 
3869         while ( *src->dependentfiles[i] ) 
3870         {
3871                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
3872                         in_use = True;
3873                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
3874                         trim_dependent_file( src->dependentfiles, i );
3875                 }
3876                 else
3877                         i++;
3878         }               
3879                 
3880         return in_use;
3881 }
3882
3883 /****************************************************************************
3884   Determine whether or not a particular driver files are currently being 
3885   used by any other driver.  
3886   
3887   Return value is True if any files were in use by other drivers
3888   and False otherwise.
3889   
3890   Upon return, *info has been modified to only contain the driver files
3891   which are not in use
3892 ****************************************************************************/
3893
3894 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3895 {
3896         int                             i;
3897         int                             ndrivers;
3898         uint32                          version;
3899         fstring                         *list = NULL;
3900         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
3901         
3902         if ( !info )
3903                 return False;
3904         
3905         version = info->cversion;
3906         
3907         /* loop over all driver versions */
3908         
3909         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
3910         
3911         /* get the list of drivers */
3912                 
3913         list = NULL;
3914         ndrivers = get_ntdrivers(&list, info->environment, version);
3915                 
3916         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
3917                 ndrivers, info->environment, version));
3918
3919         /* check each driver for overlap in files */
3920                 
3921         for (i=0; i<ndrivers; i++) 
3922         {
3923                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3924                         
3925                 ZERO_STRUCT(driver);
3926                         
3927                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], 
3928                         info->environment, version)) )
3929                 {
3930                         SAFE_FREE(list);
3931                         return True;
3932                 }
3933                         
3934                 /* check if d2 uses any files from d1 */
3935                 /* only if this is a different driver than the one being deleted */
3936                         
3937                 if ( !strequal(info->name, driver.info_3->name) )
3938                 {
3939                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
3940                                 free_a_printer_driver(driver, 3);
3941                                 SAFE_FREE( list );
3942                                 return True;
3943                         }
3944                 }
3945         
3946                 free_a_printer_driver(driver, 3);
3947         }       
3948         
3949         SAFE_FREE(list);
3950         
3951         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
3952         
3953         driver.info_3 = info;
3954         
3955         if ( DEBUGLEVEL >= 20 )
3956                 dump_a_printer_driver( driver, 3 );
3957         
3958         return False;
3959 }
3960
3961 /****************************************************************************
3962   Actually delete the driver files.  Make sure that 
3963   printer_driver_files_in_use() return False before calling 
3964   this.
3965 ****************************************************************************/
3966
3967 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
3968 {
3969         int i = 0;
3970         char *s;
3971         connection_struct *conn;
3972         DATA_BLOB null_pw;
3973         NTSTATUS nt_status;
3974         
3975         if ( !info_3 )
3976                 return False;
3977                 
3978         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
3979         
3980         /*
3981          * Connect to the print$ share under the same account as the 
3982          * user connected to the rpc pipe. Note we must be root to 
3983          * do this.
3984          */
3985          
3986         become_root();
3987         null_pw = data_blob( NULL, 0 );
3988         conn = make_connection_with_chdir( "print$", null_pw, "A:", user->vuid, &nt_status );
3989         unbecome_root();
3990         
3991         if ( !conn ) {
3992                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
3993                 return False;
3994         }
3995
3996         /* Save who we are - we are temporarily becoming the connection user. */
3997
3998         if ( !become_user(conn, conn->vuid) ) {
3999                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4000                 return False;
4001         }
4002
4003         /* now delete the files; must strip the '\print$' string from 
4004            fron of path                                                */
4005         
4006         if ( *info_3->driverpath ) {
4007                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4008                         DEBUG(10,("deleting driverfile [%s]\n", s));
4009                         unlink_internals(conn, 0, s);
4010                 }
4011         }
4012                 
4013         if ( *info_3->configfile ) {
4014                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4015                         DEBUG(10,("deleting configfile [%s]\n", s));
4016                         unlink_internals(conn, 0, s);
4017                 }
4018         }
4019         
4020         if ( *info_3->datafile ) {
4021                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4022                         DEBUG(10,("deleting datafile [%s]\n", s));
4023                         unlink_internals(conn, 0, s);
4024                 }
4025         }
4026         
4027         if ( *info_3->helpfile ) {
4028                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4029                         DEBUG(10,("deleting helpfile [%s]\n", s));
4030                         unlink_internals(conn, 0, s);
4031                 }
4032         }
4033         
4034         /* check if we are done removing files */
4035         
4036         if ( info_3->dependentfiles )
4037         {
4038                 while ( *info_3->dependentfiles[i] ) {
4039                         char *file;
4040
4041                         /* bypass the "\print$" portion of the path */
4042                         
4043                         if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL )
4044                         {
4045                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4046                                 unlink_internals(conn, 0, file );
4047                         }
4048                         
4049                         i++;
4050                 }
4051         }
4052
4053         unbecome_user();
4054         
4055         return True;
4056 }
4057
4058 /****************************************************************************
4059  Remove a printer driver from the TDB.  This assumes that the the driver was
4060  previously looked up.
4061  ***************************************************************************/
4062
4063 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4064                               uint32 version, BOOL delete_files )
4065 {
4066         pstring         key;
4067         fstring         arch;
4068         TDB_DATA        kbuf, dbuf;
4069         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4070
4071         /* delete the tdb data first */
4072
4073         get_short_archi(arch, info_3->environment);
4074         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4075                 arch, version, info_3->name);
4076
4077         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4078                 key, delete_files ? "TRUE" : "FALSE" ));
4079
4080         ctr.info_3 = info_3;
4081         dump_a_printer_driver( ctr, 3 );
4082
4083         kbuf.dptr=key;
4084         kbuf.dsize=strlen(key)+1;
4085
4086         /* check if the driver actually exists for this environment */
4087         
4088         dbuf = tdb_fetch( tdb_drivers, kbuf );
4089         if ( !dbuf.dptr ) {
4090                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4091                 return WERR_UNKNOWN_PRINTER_DRIVER;
4092         }
4093                 
4094         SAFE_FREE( dbuf.dptr );
4095         
4096         /* ok... the driver exists so the delete should return success */
4097                 
4098         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4099                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4100                 return WERR_ACCESS_DENIED;
4101         }
4102
4103         /*
4104          * now delete any associated files if delete_files == True
4105          * even if this part failes, we return succes because the
4106          * driver doesn not exist any more
4107          */
4108
4109         if ( delete_files )
4110                 delete_driver_files( info_3, user );
4111                         
4112                 
4113         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4114
4115         return WERR_OK;
4116         }
4117         
4118 /****************************************************************************
4119  Store a security desc for a printer.
4120 ****************************************************************************/
4121
4122 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4123 {
4124         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4125         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4126         prs_struct ps;
4127         TALLOC_CTX *mem_ctx = NULL;
4128         fstring key;
4129         WERROR status;
4130
4131         mem_ctx = talloc_init();
4132         if (mem_ctx == NULL)
4133                 return WERR_NOMEM;
4134
4135         /* The old owner and group sids of the security descriptor are not
4136            present when new ACEs are added or removed by changing printer
4137            permissions through NT.  If they are NULL in the new security
4138            descriptor then copy them over from the old one. */
4139
4140         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4141                 DOM_SID *owner_sid, *group_sid;
4142                 SEC_ACL *dacl, *sacl;
4143                 SEC_DESC *psd = NULL;
4144                 size_t size;
4145
4146                 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4147
4148                 /* Pick out correct owner and group sids */
4149
4150                 owner_sid = secdesc_ctr->sec->owner_sid ?
4151                         secdesc_ctr->sec->owner_sid :
4152                         old_secdesc_ctr->sec->owner_sid;
4153
4154                 group_sid = secdesc_ctr->sec->grp_sid ?
4155                         secdesc_ctr->sec->grp_sid :
4156                         old_secdesc_ctr->sec->grp_sid;
4157
4158                 dacl = secdesc_ctr->sec->dacl ?
4159                         secdesc_ctr->sec->dacl :
4160                         old_secdesc_ctr->sec->dacl;
4161
4162                 sacl = secdesc_ctr->sec->sacl ?
4163                         secdesc_ctr->sec->sacl :
4164                         old_secdesc_ctr->sec->sacl;
4165
4166                 /* Make a deep copy of the security descriptor */
4167
4168                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
4169                                     owner_sid, group_sid,
4170                                     sacl,
4171                                     dacl,
4172                                     &size);
4173
4174                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4175         }
4176
4177         if (!new_secdesc_ctr) {
4178                 new_secdesc_ctr = secdesc_ctr;
4179         }
4180
4181         /* Store the security descriptor in a tdb */
4182
4183         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4184                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4185
4186         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4187                              &ps, 1)) {
4188                 status = WERR_BADFUNC;
4189                 goto out;
4190         }
4191
4192         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4193
4194         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4195                 status = WERR_OK;
4196         } else {
4197                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4198                 status = WERR_BADFUNC;
4199         }
4200
4201         /* Free malloc'ed memory */
4202
4203  out:
4204
4205         prs_mem_free(&ps);
4206         if (mem_ctx)
4207                 talloc_destroy(mem_ctx);
4208         return status;
4209 }
4210
4211 /****************************************************************************
4212  Construct a default security descriptor buffer for a printer.
4213 ****************************************************************************/
4214
4215 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4216 {
4217         SEC_ACE ace[3];
4218         SEC_ACCESS sa;
4219         SEC_ACL *psa = NULL;
4220         SEC_DESC_BUF *sdb = NULL;
4221         SEC_DESC *psd = NULL;
4222         DOM_SID owner_sid;
4223         size_t sd_size;
4224
4225         /* Create an ACE where Everyone is allowed to print */
4226
4227         init_sec_access(&sa, PRINTER_ACE_PRINT);
4228         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4229                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4230
4231         /* Make the security descriptor owned by the Administrators group
4232            on the PDC of the domain. */
4233
4234         if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4235                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4236         } else {
4237
4238                 /* Backup plan - make printer owned by admins.
4239                    This should emulate a lanman printer as security
4240                    settings can't be changed. */
4241
4242                 sid_copy(&owner_sid, get_global_sam_sid());
4243                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4244         }
4245
4246         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4247         init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4248                      sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4249                      SEC_ACE_FLAG_INHERIT_ONLY);
4250
4251         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4252         init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4253                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4254
4255         /* The ACL revision number in rpc_secdesc.h differs from the one
4256            created by NT when setting ACE entries in printer
4257            descriptors.  NT4 complains about the property being edited by a
4258            NT5 machine. */
4259
4260         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4261                 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4262                                     &owner_sid, NULL,
4263                                     NULL, psa, &sd_size);
4264         }
4265
4266         if (!psd) {
4267                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4268                 return NULL;
4269         }
4270
4271         sdb = make_sec_desc_buf(ctx, sd_size, psd);
4272
4273         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4274                  (unsigned int)sd_size));
4275
4276         return sdb;
4277 }
4278
4279 /****************************************************************************
4280  Get a security desc for a printer.
4281 ****************************************************************************/
4282
4283 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4284 {
4285         prs_struct ps;
4286         fstring key;
4287         char *temp;
4288
4289         if ((temp = strchr(printername + 2, '\\'))) {
4290                 printername = temp + 1;
4291         }
4292
4293         /* Fetch security descriptor from tdb */
4294
4295         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4296
4297         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4298             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4299
4300                 DEBUG(4,("using default secdesc for %s\n", printername));
4301
4302                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4303                         return False;
4304                 }
4305
4306                 /* Save default security descriptor for later */
4307
4308                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4309                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4310
4311                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4312                         tdb_prs_store(tdb_printers, key, &ps);
4313
4314                 prs_mem_free(&ps);
4315
4316                 return True;
4317         }
4318
4319         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4320            this security descriptor has been created when winbindd was
4321            down.  Take ownership of security descriptor. */
4322
4323         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4324                 DOM_SID owner_sid;
4325
4326                 /* Change sd owner to workgroup administrator */
4327
4328                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4329                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4330                         SEC_DESC *psd = NULL;
4331                         size_t size;
4332
4333                         /* Create new sd */
4334
4335                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4336
4337                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4338                                             &owner_sid,
4339                                             (*secdesc_ctr)->sec->grp_sid,
4340                                             (*secdesc_ctr)->sec->sacl,
4341                                             (*secdesc_ctr)->sec->dacl,
4342                                             &size);
4343
4344                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4345
4346                         /* Swap with other one */
4347
4348                         *secdesc_ctr = new_secdesc_ctr;
4349
4350                         /* Set it */
4351
4352                         nt_printing_setsec(printername, *secdesc_ctr);
4353                 }
4354         }
4355
4356         if (DEBUGLEVEL >= 10) {
4357                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4358                 int i;
4359
4360                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4361                            printername, the_acl->num_aces));
4362
4363                 for (i = 0; i < the_acl->num_aces; i++) {
4364                         fstring sid_str;
4365
4366                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4367
4368                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4369                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
4370                                    the_acl->ace[i].info.mask)); 
4371                 }
4372         }
4373
4374         prs_mem_free(&ps);
4375         return True;
4376 }
4377
4378 /* error code:
4379         0: everything OK
4380         1: level not implemented
4381         2: file doesn't exist
4382         3: can't allocate memory
4383         4: can't free memory
4384         5: non existant struct
4385 */
4386
4387 /*
4388         A printer and a printer driver are 2 different things.
4389         NT manages them separatelly, Samba does the same.
4390         Why ? Simply because it's easier and it makes sense !
4391         
4392         Now explanation: You have 3 printers behind your samba server,
4393         2 of them are the same make and model (laser A and B). But laser B
4394         has an 3000 sheet feeder and laser A doesn't such an option.
4395         Your third printer is an old dot-matrix model for the accounting :-).
4396         
4397         If the /usr/local/samba/lib directory (default dir), you will have
4398         5 files to describe all of this.
4399         
4400         3 files for the printers (1 by printer):
4401                 NTprinter_laser A
4402                 NTprinter_laser B
4403                 NTprinter_accounting
4404         2 files for the drivers (1 for the laser and 1 for the dot matrix)
4405                 NTdriver_printer model X
4406                 NTdriver_printer model Y
4407
4408 jfm: I should use this comment for the text file to explain
4409         same thing for the forms BTW.
4410         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4411
4412 */
4413
4414 /* Convert generic access rights to printer object specific access rights.
4415    It turns out that NT4 security descriptors use generic access rights and
4416    NT5 the object specific ones. */
4417
4418 void map_printer_permissions(SEC_DESC *sd)
4419 {
4420         int i;
4421
4422         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4423                 se_map_generic(&sd->dacl->ace[i].info.mask,
4424                                &printer_generic_mapping);
4425         }
4426 }
4427
4428 /****************************************************************************
4429  Check a user has permissions to perform the given operation.  We use the
4430  permission constants defined in include/rpc_spoolss.h to check the various
4431  actions we perform when checking printer access.
4432
4433    PRINTER_ACCESS_ADMINISTER:
4434        print_queue_pause, print_queue_resume, update_printer_sec,
4435        update_printer, spoolss_addprinterex_level_2,
4436        _spoolss_setprinterdata
4437
4438    PRINTER_ACCESS_USE:
4439        print_job_start
4440
4441    JOB_ACCESS_ADMINISTER:
4442        print_job_delete, print_job_pause, print_job_resume,
4443        print_queue_purge
4444
4445  ****************************************************************************/
4446 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4447 {
4448         SEC_DESC_BUF *secdesc = NULL;
4449         uint32 access_granted;
4450         NTSTATUS status;
4451         BOOL result;
4452         const char *pname;
4453         TALLOC_CTX *mem_ctx = NULL;
4454         extern struct current_user current_user;
4455         
4456         /* If user is NULL then use the current_user structure */
4457
4458         if (!user)
4459                 user = &current_user;
4460
4461         /* Always allow root or printer admins to do anything */
4462
4463         if (user->uid == 0 ||
4464             user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
4465                 return True;
4466         }
4467
4468         /* Get printer name */
4469
4470         pname = PRINTERNAME(snum);
4471
4472         if (!pname || !*pname) {
4473                 errno = EACCES;
4474                 return False;
4475         }
4476
4477         /* Get printer security descriptor */
4478
4479         if(!(mem_ctx = talloc_init())) {
4480                 errno = ENOMEM;
4481                 return False;
4482         }
4483
4484         nt_printing_getsec(mem_ctx, pname, &secdesc);
4485
4486         if (access_type == JOB_ACCESS_ADMINISTER) {
4487                 SEC_DESC_BUF *parent_secdesc = secdesc;
4488
4489                 /* Create a child security descriptor to check permissions
4490                    against.  This is because print jobs are child objects
4491                    objects of a printer. */
4492
4493                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4494
4495                 /* Now this is the bit that really confuses me.  The access
4496                    type needs to be changed from JOB_ACCESS_ADMINISTER to
4497                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
4498                    to do with the child (job) object becoming like a
4499                    printer??  -tpot */
4500
4501                 access_type = PRINTER_ACCESS_ADMINISTER;
4502         }
4503         
4504         /* Check access */
4505         
4506         map_printer_permissions(secdesc->sec);
4507
4508         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4509                                  &access_granted, &status);
4510
4511         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4512
4513         talloc_destroy(mem_ctx);
4514         
4515         if (!result)
4516                 errno = EACCES;
4517
4518         return result;
4519 }
4520
4521 /****************************************************************************
4522  Check the time parameters allow a print operation.
4523 *****************************************************************************/
4524
4525 BOOL print_time_access_check(int snum)
4526 {
4527         NT_PRINTER_INFO_LEVEL *printer = NULL;
4528         BOOL ok = False;
4529         time_t now = time(NULL);
4530         struct tm *t;
4531         uint32 mins;
4532
4533         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4534                 return False;
4535
4536         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4537                 ok = True;
4538
4539         t = gmtime(&now);
4540         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4541
4542         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4543                 ok = True;
4544
4545         free_a_printer(&printer, 2);
4546
4547         if (!ok)
4548                 errno = EACCES;
4549
4550         return ok;
4551 }
4552