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