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