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