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