s3-spoolss: Migrated NT_DEVICEMODE to spoolss_DeviceMode.
[abartlet/samba.git/.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(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
2293 {
2294         enum ndr_err_code ndr_err;
2295         DATA_BLOB blob;
2296         int len = 0;
2297
2298         if (devmode) {
2299                 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
2300                                                devmode,
2301                                                (ndr_push_flags_fn_t)
2302                                                ndr_push_spoolss_DeviceMode);
2303                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2304                         DEBUG(10, ("pack_devicemode: "
2305                                    "error encoding spoolss_DeviceMode\n"));
2306                         goto done;
2307                 }
2308         } else {
2309                 ZERO_STRUCT(blob);
2310         }
2311
2312         len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
2313
2314         if (devmode) {
2315                 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
2316         }
2317
2318 done:
2319         return len;
2320 }
2321
2322 /****************************************************************************
2323 ****************************************************************************/
2324 int unpack_devicemode(TALLOC_CTX *mem_ctx,
2325                       const uint8 *buf, int buflen,
2326                       struct spoolss_DeviceMode **devmode)
2327 {
2328         struct spoolss_DeviceMode *dm;
2329         enum ndr_err_code ndr_err;
2330         char *data = NULL;
2331         int data_len = 0;
2332         DATA_BLOB blob;
2333         int len = 0;
2334
2335         *devmode = NULL;
2336
2337         len = tdb_unpack(buf, buflen, "B", &data_len, &data);
2338         if (!data) {
2339                 return len;
2340         }
2341
2342         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2343         if (!dm) {
2344                 goto done;
2345         }
2346
2347         blob = data_blob_const(data, data_len);
2348
2349         ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
2350                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
2351         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2352                 DEBUG(10, ("unpack_devicemode: "
2353                            "error parsing spoolss_DeviceMode\n"));
2354                 goto done;
2355         }
2356
2357         DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
2358                   dm->devicename, dm->formname));
2359         if (dm->driverextra_data.data) {
2360                 DEBUG(8, ("with a private section of %d bytes\n",
2361                           dm->__driverextra_length));
2362         }
2363
2364         *devmode = dm;
2365
2366 done:
2367         SAFE_FREE(data);
2368         return len;
2369 }
2370
2371 /****************************************************************************
2372  Pack all values in all printer keys
2373  ***************************************************************************/
2374
2375 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2376 {
2377         int             len = 0;
2378         int             i, j;
2379         struct regval_blob      *val;
2380         struct regval_ctr       *val_ctr;
2381         char *path = NULL;
2382         int             num_values;
2383
2384         if ( !data )
2385                 return 0;
2386
2387         /* loop over all keys */
2388
2389         for ( i=0; i<data->num_keys; i++ ) {
2390                 val_ctr = data->keys[i].values;
2391                 num_values = regval_ctr_numvals( val_ctr );
2392
2393                 /* pack the keyname followed by a empty value */
2394
2395                 len += tdb_pack(buf+len, buflen-len, "pPdB",
2396                                 &data->keys[i].name,
2397                                 data->keys[i].name,
2398                                 REG_NONE,
2399                                 0,
2400                                 NULL);
2401
2402                 /* now loop over all values */
2403
2404                 for ( j=0; j<num_values; j++ ) {
2405                         /* pathname should be stored as <key>\<value> */
2406
2407                         val = regval_ctr_specific_value( val_ctr, j );
2408                         if (asprintf(&path, "%s\\%s",
2409                                         data->keys[i].name,
2410                                         regval_name(val)) < 0) {
2411                                 return -1;
2412                         }
2413
2414                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2415                                         val,
2416                                         path,
2417                                         regval_type(val),
2418                                         regval_size(val),
2419                                         regval_data_p(val) );
2420
2421                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2422                         SAFE_FREE(path);
2423                 }
2424
2425         }
2426
2427         /* terminator */
2428
2429         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2430
2431         return len;
2432 }
2433
2434
2435 /****************************************************************************
2436  Delete a printer - this just deletes the printer info file, any open
2437  handles are not affected.
2438 ****************************************************************************/
2439
2440 uint32 del_a_printer(const char *sharename)
2441 {
2442         TDB_DATA kbuf;
2443         char *printdb_path = NULL;
2444         TALLOC_CTX *ctx = talloc_tos();
2445
2446         kbuf = make_printer_tdbkey(ctx, sharename);
2447         tdb_delete(tdb_printers, kbuf);
2448
2449         kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2450         tdb_delete(tdb_printers, kbuf);
2451
2452         close_all_print_db();
2453
2454         if (geteuid() == sec_initial_uid()) {
2455                 if (asprintf(&printdb_path, "%s%s.tdb",
2456                                 cache_path("printing/"),
2457                                 sharename) < 0) {
2458                         return (uint32)-1;
2459                 }
2460                 unlink(printdb_path);
2461                 SAFE_FREE(printdb_path);
2462         }
2463
2464         return 0;
2465 }
2466
2467 /****************************************************************************
2468 ****************************************************************************/
2469 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2470 {
2471         uint8 *buf;
2472         int buflen, len;
2473         int retlen;
2474         WERROR ret;
2475         TDB_DATA kbuf, dbuf;
2476
2477         /*
2478          * in addprinter: no servername and the printer is the name
2479          * in setprinter: servername is \\server
2480          *                and printer is \\server\\printer
2481          *
2482          * Samba manages only local printers.
2483          * we currently don't support things like i
2484          * path=\\other_server\printer
2485          *
2486          * We only store the printername, not \\server\printername
2487          */
2488
2489         if ( info->servername[0] != '\0' ) {
2490                 trim_string(info->printername, info->servername, NULL);
2491                 trim_char(info->printername, '\\', '\0');
2492                 info->servername[0]='\0';
2493         }
2494
2495         /*
2496          * JFM: one day I'll forget.
2497          * below that's info->portname because that's the SAMBA sharename
2498          * and I made NT 'thinks' it's the portname
2499          * the info->sharename is the thing you can name when you add a printer
2500          * that's the short-name when you create shared printer for 95/98
2501          * So I've made a limitation in SAMBA: you can only have 1 printer model
2502          * behind a SAMBA share.
2503          */
2504
2505         buf = NULL;
2506         buflen = 0;
2507
2508  again:
2509         len = 0;
2510         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2511                         info->attributes,
2512                         info->priority,
2513                         info->default_priority,
2514                         info->starttime,
2515                         info->untiltime,
2516                         info->status,
2517                         info->cjobs,
2518                         info->averageppm,
2519                         info->changeid,
2520                         info->c_setprinter,
2521                         info->setuptime,
2522                         info->servername,
2523                         info->printername,
2524                         info->sharename,
2525                         info->portname,
2526                         info->drivername,
2527                         info->comment,
2528                         info->location,
2529                         info->sepfile,
2530                         info->printprocessor,
2531                         info->datatype,
2532                         info->parameters);
2533
2534         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2535         retlen = pack_values( info->data, buf+len, buflen-len );
2536         if (retlen == -1) {
2537                 ret = WERR_NOMEM;
2538                 goto done;
2539         }
2540         len += retlen;
2541
2542         if (buflen != len) {
2543                 buf = (uint8 *)SMB_REALLOC(buf, len);
2544                 if (!buf) {
2545                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2546                         ret = WERR_NOMEM;
2547                         goto done;
2548                 }
2549                 buflen = len;
2550                 goto again;
2551         }
2552
2553         kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2554
2555         dbuf.dptr = buf;
2556         dbuf.dsize = len;
2557
2558         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2559
2560 done:
2561         if (!W_ERROR_IS_OK(ret))
2562                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2563
2564         SAFE_FREE(buf);
2565
2566         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2567                  info->sharename, info->drivername, info->portname, len));
2568
2569         return ret;
2570 }
2571
2572 /****************************************************************************
2573  Create and allocate a default devicemode.
2574 ****************************************************************************/
2575
2576 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2577                                       const char *devicename,
2578                                       struct spoolss_DeviceMode **devmode)
2579 {
2580         struct spoolss_DeviceMode *dm;
2581         char *dname;
2582
2583         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2584         if (dm == NULL) {
2585                 return WERR_NOMEM;
2586         }
2587
2588         dname = talloc_asprintf(dm, "%s", devicename);
2589         if (dname == NULL) {
2590                 return WERR_NOMEM;
2591         }
2592         if (strlen(dname) > MAXDEVICENAME) {
2593                 dname[MAXDEVICENAME] = '\0';
2594         }
2595         dm->devicename = dname;
2596
2597         dm->formname = talloc_strdup(dm, "Letter");
2598         if (dm->formname == NULL) {
2599                 return WERR_NOMEM;
2600         }
2601
2602         dm->specversion          = DMSPEC_NT4_AND_ABOVE;
2603         dm->driverversion        = 0x0400;
2604         dm->size                 = 0x00DC;
2605         dm->__driverextra_length = 0;
2606         dm->fields               = DEVMODE_FORMNAME |
2607                                    DEVMODE_TTOPTION |
2608                                    DEVMODE_PRINTQUALITY |
2609                                    DEVMODE_DEFAULTSOURCE |
2610                                    DEVMODE_COPIES |
2611                                    DEVMODE_SCALE |
2612                                    DEVMODE_PAPERSIZE |
2613                                    DEVMODE_ORIENTATION;
2614         dm->orientation          = DMORIENT_PORTRAIT;
2615         dm->papersize            = DMPAPER_LETTER;
2616         dm->paperlength          = 0;
2617         dm->paperwidth           = 0;
2618         dm->scale                = 0x64;
2619         dm->copies               = 1;
2620         dm->defaultsource        = DMBIN_FORMSOURCE;
2621         dm->printquality         = DMRES_HIGH;           /* 0x0258 */
2622         dm->color                = DMRES_MONOCHROME;
2623         dm->duplex               = DMDUP_SIMPLEX;
2624         dm->yresolution          = 0;
2625         dm->ttoption             = DMTT_SUBDEV;
2626         dm->collate              = DMCOLLATE_FALSE;
2627         dm->icmmethod            = 0;
2628         dm->icmintent            = 0;
2629         dm->mediatype            = 0;
2630         dm->dithertype           = 0;
2631
2632         dm->logpixels            = 0;
2633         dm->bitsperpel           = 0;
2634         dm->pelswidth            = 0;
2635         dm->pelsheight           = 0;
2636         dm->displayflags         = 0;
2637         dm->displayfrequency     = 0;
2638         dm->reserved1            = 0;
2639         dm->reserved2            = 0;
2640         dm->panningwidth         = 0;
2641         dm->panningheight        = 0;
2642
2643         dm->driverextra_data.data = NULL;
2644         dm->driverextra_data.length = 0;
2645
2646         *devmode = dm;
2647         return WERR_OK;
2648 }
2649
2650 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2651                                       struct spoolss_security_descriptor **secdesc)
2652 {
2653         struct security_ace ace[7];     /* max number of ace entries */
2654         int i = 0;
2655         uint32_t sa;
2656         struct security_acl *psa = NULL;
2657         struct security_descriptor *psd = NULL;
2658         struct dom_sid adm_sid;
2659         size_t sd_size;
2660
2661         /* Create an ACE where Everyone is allowed to print */
2662
2663         sa = PRINTER_ACE_PRINT;
2664         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2665                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2666
2667         /* Add the domain admins group if we are a DC */
2668
2669         if ( IS_DC ) {
2670                 struct dom_sid domadmins_sid;
2671
2672                 sid_compose(&domadmins_sid, get_global_sam_sid(),
2673                             DOMAIN_RID_ADMINS);
2674
2675                 sa = PRINTER_ACE_FULL_CONTROL;
2676                 init_sec_ace(&ace[i++], &domadmins_sid,
2677                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2678                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2679                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2680                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2681         }
2682         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2683                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2684
2685                 sa = PRINTER_ACE_FULL_CONTROL;
2686                 init_sec_ace(&ace[i++], &adm_sid,
2687                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2688                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2689                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2690                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2691         }
2692
2693         /* add BUILTIN\Administrators as FULL CONTROL */
2694
2695         sa = PRINTER_ACE_FULL_CONTROL;
2696         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2697                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2698                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2699         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2700                 SEC_ACE_TYPE_ACCESS_ALLOWED,
2701                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2702
2703         /* add BUILTIN\Print Operators as FULL CONTROL */
2704
2705         sa = PRINTER_ACE_FULL_CONTROL;
2706         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2707                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2708                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2709         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2710                 SEC_ACE_TYPE_ACCESS_ALLOWED,
2711                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2712
2713         /* Make the security descriptor owned by the BUILTIN\Administrators */
2714
2715         /* The ACL revision number in rpc_secdesc.h differs from the one
2716            created by NT when setting ACE entries in printer
2717            descriptors.  NT4 complains about the property being edited by a
2718            NT5 machine. */
2719
2720         if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2721                 psd = make_sec_desc(mem_ctx,
2722                                     SD_REVISION,
2723                                     SEC_DESC_SELF_RELATIVE,
2724                                     &global_sid_Builtin_Administrators,
2725                                     &global_sid_Builtin_Administrators,
2726                                     NULL,
2727                                     psa,
2728                                     &sd_size);
2729         }
2730
2731         if (psd == NULL) {
2732                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2733                 return WERR_NOMEM;
2734         }
2735
2736         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2737                  (unsigned int)sd_size));
2738
2739         *secdesc = psd;
2740
2741         return WERR_OK;
2742 }
2743
2744 /****************************************************************************
2745  Allocate and initialize a new slot.
2746 ***************************************************************************/
2747
2748 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2749 {
2750         NT_PRINTER_KEY  *d;
2751         int             key_index;
2752         WERROR werr;
2753
2754         if ( !name || !data )
2755                 return -1;
2756
2757         /* allocate another slot in the NT_PRINTER_KEY array */
2758
2759         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2760                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2761                 return -1;
2762         }
2763
2764         data->keys = d;
2765
2766         key_index = data->num_keys;
2767
2768         /* initialze new key */
2769
2770         data->keys[key_index].name = talloc_strdup( data, name );
2771
2772         werr = regval_ctr_init(data, &(data->keys[key_index].values));
2773         if (!W_ERROR_IS_OK(werr)) {
2774                 return -1;
2775         }
2776
2777         data->num_keys++;
2778
2779         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2780
2781         return key_index;
2782 }
2783
2784 /****************************************************************************
2785  search for a registry key name in the existing printer data
2786  ***************************************************************************/
2787
2788 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2789 {
2790         int i;
2791
2792         for ( i=0; i<data->num_keys; i++ ) {
2793                 if ( strequal( data->keys[i].name, name ) ) {
2794
2795                         /* cleanup memory */
2796
2797                         TALLOC_FREE( data->keys[i].name );
2798                         TALLOC_FREE( data->keys[i].values );
2799
2800                         /* if not the end of the array, move remaining elements down one slot */
2801
2802                         data->num_keys--;
2803                         if ( data->num_keys && (i < data->num_keys) )
2804                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2805
2806                         break;
2807                 }
2808         }
2809
2810
2811         return data->num_keys;
2812 }
2813
2814 /****************************************************************************
2815  search for a registry key name in the existing printer data
2816  ***************************************************************************/
2817
2818 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2819 {
2820         int             key_index = -1;
2821         int             i;
2822
2823         if ( !data || !name )
2824                 return -1;
2825
2826         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2827
2828         /* loop over all existing keys */
2829
2830         for ( i=0; i<data->num_keys; i++ ) {
2831                 if ( strequal(data->keys[i].name, name) ) {
2832                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2833                         key_index = i;
2834                         break;
2835
2836                 }
2837         }
2838
2839         return key_index;
2840 }
2841
2842 /****************************************************************************
2843  ***************************************************************************/
2844
2845 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2846 {
2847         int     i, j;
2848         int     key_len;
2849         int     num_subkeys = 0;
2850         char    *p;
2851         fstring *subkeys_ptr = NULL;
2852         fstring subkeyname;
2853
2854         *subkeys = NULL;
2855
2856         if ( !data )
2857                 return 0;
2858
2859         if ( !key )
2860                 return -1;
2861
2862         /* special case of asking for the top level printer data registry key names */
2863
2864         if ( strlen(key) == 0 ) {
2865                 for ( i=0; i<data->num_keys; i++ ) {
2866
2867                         /* found a match, so allocate space and copy the name */
2868
2869                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2870                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2871                                         num_subkeys+1));
2872                                 return -1;
2873                         }
2874
2875                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2876                         num_subkeys++;
2877                 }
2878
2879                 goto done;
2880         }
2881
2882         /* asking for the subkeys of some key */
2883         /* subkey paths are stored in the key name using '\' as the delimiter */
2884
2885         for ( i=0; i<data->num_keys; i++ ) {
2886                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2887
2888                         /* if we found the exact key, then break */
2889                         key_len = strlen( key );
2890                         if ( strlen(data->keys[i].name) == key_len )
2891                                 break;
2892
2893                         /* get subkey path */
2894
2895                         p = data->keys[i].name + key_len;
2896                         if ( *p == '\\' )
2897                                 p++;
2898                         fstrcpy( subkeyname, p );
2899                         if ( (p = strchr( subkeyname, '\\' )) )
2900                                 *p = '\0';
2901
2902                         /* don't add a key more than once */
2903
2904                         for ( j=0; j<num_subkeys; j++ ) {
2905                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2906                                         break;
2907                         }
2908
2909                         if ( j != num_subkeys )
2910                                 continue;
2911
2912                         /* found a match, so allocate space and copy the name */
2913
2914                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2915                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2916                                         num_subkeys+1));
2917                                 return 0;
2918                         }
2919
2920                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2921                         num_subkeys++;
2922                 }
2923
2924         }
2925
2926         /* return error if the key was not found */
2927
2928         if ( i == data->num_keys ) {
2929                 SAFE_FREE(subkeys_ptr);
2930                 return -1;
2931         }
2932
2933 done:
2934         /* tag off the end */
2935
2936         if (num_subkeys)
2937                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2938
2939         *subkeys = subkeys_ptr;
2940
2941         return num_subkeys;
2942 }
2943
2944 #ifdef HAVE_ADS
2945 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2946                             const char *sz)
2947 {
2948         regval_ctr_delvalue(ctr, val_name);
2949         regval_ctr_addvalue_sz(ctr, val_name, sz);
2950 }
2951
2952 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
2953                                uint32 dword)
2954 {
2955         regval_ctr_delvalue(ctr, val_name);
2956         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2957                             (uint8 *) &dword, sizeof(dword));
2958 }
2959
2960 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
2961                               bool b)
2962 {
2963         uint8 bin_bool = (b ? 1 : 0);
2964         regval_ctr_delvalue(ctr, val_name);
2965         regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2966                             (uint8 *) &bin_bool, sizeof(bin_bool));
2967 }
2968
2969 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2970                                          const char *multi_sz)
2971 {
2972         const char *a[2];
2973
2974         a[0] = multi_sz;
2975         a[1] = NULL;
2976
2977         regval_ctr_delvalue(ctr, val_name);
2978         regval_ctr_addvalue_multi_sz(ctr, val_name, a);
2979 }
2980
2981 /****************************************************************************
2982  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2983  *
2984  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2985  * @return bool indicating success or failure
2986  ***************************************************************************/
2987
2988 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2989 {
2990         struct regval_ctr *ctr = NULL;
2991         fstring longname;
2992         const char *dnssuffix;
2993         char *allocated_string = NULL;
2994         const char *ascii_str;
2995         int i;
2996
2997         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2998                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2999         ctr = info2->data->keys[i].values;
3000
3001         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3002         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3003
3004         /* we make the assumption that the netbios name is the same
3005            as the DNS name sinc ethe former will be what we used to
3006            join the domain */
3007
3008         dnssuffix = get_mydnsdomname(talloc_tos());
3009         if (dnssuffix && *dnssuffix) {
3010                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3011         } else {
3012                 fstrcpy( longname, global_myname() );
3013         }
3014
3015         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3016
3017         if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3018                 return false;
3019         }
3020         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3021         SAFE_FREE(allocated_string);
3022
3023         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3024         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3025         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3026         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3027         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3028         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3029         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3030         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3031         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3032
3033         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3034                           (info2->attributes &
3035                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3036
3037         switch (info2->attributes & 0x3) {
3038         case 0:
3039                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3040                 break;
3041         case 1:
3042                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3043                 break;
3044         case 2:
3045                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3046                 break;
3047         default:
3048                 ascii_str = "unknown";
3049         }
3050         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3051
3052         return True;
3053 }
3054
3055 /*****************************************************************
3056  ****************************************************************/
3057
3058 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3059                                struct GUID guid)
3060 {
3061         int i;
3062         struct regval_ctr *ctr=NULL;
3063
3064         /* find the DsSpooler key */
3065         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3066                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3067         ctr = info2->data->keys[i].values;
3068
3069         regval_ctr_delvalue(ctr, "objectGUID");
3070
3071         /* We used to store this as a REG_BINARY but that causes
3072            Vista to whine */
3073
3074         regval_ctr_addvalue_sz(ctr, "objectGUID",
3075                                GUID_string(talloc_tos(), &guid));
3076 }
3077
3078 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3079                                      NT_PRINTER_INFO_LEVEL *printer)
3080 {
3081         ADS_STATUS ads_rc;
3082         LDAPMessage *res;
3083         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3084         char *srv_dn_utf8, **srv_cn_utf8;
3085         TALLOC_CTX *ctx;
3086         ADS_MODLIST mods;
3087         const char *attrs[] = {"objectGUID", NULL};
3088         struct GUID guid;
3089         WERROR win_rc = WERR_OK;
3090         size_t converted_size;
3091
3092         /* build the ads mods */
3093         ctx = talloc_init("nt_printer_publish_ads");
3094         if (ctx == NULL) {
3095                 return WERR_NOMEM;
3096         }
3097
3098         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3099
3100         /* figure out where to publish */
3101         ads_find_machine_acct(ads, &res, global_myname());
3102
3103         /* We use ldap_get_dn here as we need the answer
3104          * in utf8 to call ldap_explode_dn(). JRA. */
3105
3106         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3107         if (!srv_dn_utf8) {
3108                 TALLOC_FREE(ctx);
3109                 return WERR_SERVER_UNAVAILABLE;
3110         }
3111         ads_msgfree(ads, res);
3112         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3113         if (!srv_cn_utf8) {
3114                 TALLOC_FREE(ctx);
3115                 ldap_memfree(srv_dn_utf8);
3116                 return WERR_SERVER_UNAVAILABLE;
3117         }
3118         /* Now convert to CH_UNIX. */
3119         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3120                 TALLOC_FREE(ctx);
3121                 ldap_memfree(srv_dn_utf8);
3122                 ldap_memfree(srv_cn_utf8);
3123                 return WERR_SERVER_UNAVAILABLE;
3124         }
3125         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3126                 TALLOC_FREE(ctx);
3127                 ldap_memfree(srv_dn_utf8);
3128                 ldap_memfree(srv_cn_utf8);
3129                 TALLOC_FREE(srv_dn);
3130                 return WERR_SERVER_UNAVAILABLE;
3131         }
3132
3133         ldap_memfree(srv_dn_utf8);
3134         ldap_memfree(srv_cn_utf8);
3135
3136         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3137         if (!srv_cn_escaped) {
3138                 TALLOC_FREE(ctx);
3139                 return WERR_SERVER_UNAVAILABLE;
3140         }
3141         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3142         if (!sharename_escaped) {
3143                 SAFE_FREE(srv_cn_escaped);
3144                 TALLOC_FREE(ctx);
3145                 return WERR_SERVER_UNAVAILABLE;
3146         }
3147
3148         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3149
3150         SAFE_FREE(srv_cn_escaped);
3151         SAFE_FREE(sharename_escaped);
3152
3153         mods = ads_init_mods(ctx);
3154
3155         if (mods == NULL) {
3156                 SAFE_FREE(prt_dn);
3157                 TALLOC_FREE(ctx);
3158                 return WERR_NOMEM;
3159         }
3160
3161         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3162         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3163                     printer->info_2->sharename);
3164
3165         /* publish it */
3166         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3167         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3168                 int i;
3169                 for (i=0; mods[i] != 0; i++)
3170                         ;
3171                 mods[i] = (LDAPMod *)-1;
3172                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3173         }
3174
3175         if (!ADS_ERR_OK(ads_rc))
3176                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3177
3178         /* retreive the guid and store it locally */
3179         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3180                 ZERO_STRUCT(guid);
3181                 ads_pull_guid(ads, res, &guid);
3182                 ads_msgfree(ads, res);
3183                 store_printer_guid(printer->info_2, guid);
3184                 win_rc = mod_a_printer(printer, 2);
3185         }
3186         TALLOC_FREE(ctx);
3187
3188         return win_rc;
3189 }
3190
3191 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3192                                        NT_PRINTER_INFO_LEVEL *printer)
3193 {
3194         ADS_STATUS ads_rc;
3195         LDAPMessage *res = NULL;
3196         char *prt_dn = NULL;
3197
3198         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3199
3200         /* remove the printer from the directory */
3201         ads_rc = ads_find_printer_on_server(ads, &res,
3202                             printer->info_2->sharename, global_myname());
3203
3204         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3205                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3206                 if (!prt_dn) {
3207                         ads_msgfree(ads, res);
3208                         return WERR_NOMEM;
3209                 }
3210                 ads_rc = ads_del_dn(ads, prt_dn);
3211                 TALLOC_FREE(prt_dn);
3212         }
3213
3214         if (res) {
3215                 ads_msgfree(ads, res);
3216         }
3217         return WERR_OK;
3218 }
3219
3220 /****************************************************************************
3221  * Publish a printer in the directory
3222  *
3223  * @param snum describing printer service
3224  * @return WERROR indicating status of publishing
3225  ***************************************************************************/
3226
3227 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3228 {
3229         ADS_STATUS ads_rc;
3230         ADS_STRUCT *ads = NULL;
3231         NT_PRINTER_INFO_LEVEL *printer = NULL;
3232         WERROR win_rc;
3233
3234         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3235         if (!W_ERROR_IS_OK(win_rc))
3236                 goto done;
3237
3238         switch (action) {
3239         case DSPRINT_PUBLISH:
3240         case DSPRINT_UPDATE:
3241                 /* set the DsSpooler info and attributes */
3242                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3243                         win_rc = WERR_NOMEM;
3244                         goto done;
3245                 }
3246
3247                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3248                 break;
3249         case DSPRINT_UNPUBLISH:
3250                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3251                 break;
3252         default:
3253                 win_rc = WERR_NOT_SUPPORTED;
3254                 goto done;
3255         }
3256
3257         win_rc = mod_a_printer(printer, 2);
3258         if (!W_ERROR_IS_OK(win_rc)) {
3259                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3260                 goto done;
3261         }
3262
3263         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3264         if (!ads) {
3265                 DEBUG(3, ("ads_init() failed\n"));
3266                 win_rc = WERR_SERVER_UNAVAILABLE;
3267                 goto done;
3268         }
3269         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3270         SAFE_FREE(ads->auth.password);
3271         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3272                 NULL, NULL);
3273
3274         /* ads_connect() will find the DC for us */
3275         ads_rc = ads_connect(ads);
3276         if (!ADS_ERR_OK(ads_rc)) {
3277                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3278                 win_rc = WERR_ACCESS_DENIED;
3279                 goto done;
3280         }
3281
3282         switch (action) {
3283         case DSPRINT_PUBLISH:
3284         case DSPRINT_UPDATE:
3285                 win_rc = nt_printer_publish_ads(ads, printer);
3286                 break;
3287         case DSPRINT_UNPUBLISH:
3288                 win_rc = nt_printer_unpublish_ads(ads, printer);
3289                 break;
3290         }
3291
3292 done:
3293         free_a_printer(&printer, 2);
3294         ads_destroy(&ads);
3295         return win_rc;
3296 }
3297
3298 WERROR check_published_printers(void)
3299 {
3300         ADS_STATUS ads_rc;
3301         ADS_STRUCT *ads = NULL;
3302         int snum;
3303         int n_services = lp_numservices();
3304         NT_PRINTER_INFO_LEVEL *printer = NULL;
3305
3306         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3307         if (!ads) {
3308                 DEBUG(3, ("ads_init() failed\n"));
3309                 return WERR_SERVER_UNAVAILABLE;
3310         }
3311         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3312         SAFE_FREE(ads->auth.password);
3313         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3314                 NULL, NULL);
3315
3316         /* ads_connect() will find the DC for us */
3317         ads_rc = ads_connect(ads);
3318         if (!ADS_ERR_OK(ads_rc)) {
3319                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3320                 ads_destroy(&ads);
3321                 ads_kdestroy("MEMORY:prtpub_cache");
3322                 return WERR_ACCESS_DENIED;
3323         }
3324
3325         for (snum = 0; snum < n_services; snum++) {
3326                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3327                         continue;
3328
3329                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3330                                                 lp_servicename(snum))) &&
3331                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3332                         nt_printer_publish_ads(ads, printer);
3333
3334                 free_a_printer(&printer, 2);
3335         }
3336
3337         ads_destroy(&ads);
3338         ads_kdestroy("MEMORY:prtpub_cache");
3339         return WERR_OK;
3340 }
3341
3342 bool is_printer_published(Printer_entry *print_hnd, int snum,
3343                           struct GUID *guid)
3344 {
3345         NT_PRINTER_INFO_LEVEL *printer = NULL;
3346         struct regval_ctr *ctr;
3347         struct regval_blob *guid_val;
3348         WERROR win_rc;
3349         int i;
3350         bool ret = False;
3351         DATA_BLOB blob;
3352
3353         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3354
3355         if (!W_ERROR_IS_OK(win_rc) ||
3356             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3357             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3358             !(ctr = printer->info_2->data->keys[i].values) ||
3359             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3360         {
3361                 free_a_printer(&printer, 2);
3362                 return False;
3363         }
3364
3365         /* fetching printer guids really ought to be a separate function. */
3366
3367         if ( guid ) {
3368                 char *guid_str;
3369
3370                 /* We used to store the guid as REG_BINARY, then swapped
3371                    to REG_SZ for Vista compatibility so check for both */
3372
3373                 switch ( regval_type(guid_val) ){
3374                 case REG_SZ:
3375                         blob = data_blob_const(regval_data_p(guid_val),
3376                                                regval_size(guid_val));
3377                         pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3378                         ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3379                         talloc_free(guid_str);
3380                         break;
3381                 case REG_BINARY:
3382                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3383                                 ret = False;
3384                                 break;
3385                         }
3386                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3387                         break;
3388                 default:
3389                         DEBUG(0,("is_printer_published: GUID value stored as "
3390                                  "invaluid type (%d)\n", regval_type(guid_val) ));
3391                         break;
3392                 }
3393         }
3394
3395         free_a_printer(&printer, 2);
3396         return ret;
3397 }
3398 #else
3399 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3400 {
3401         return WERR_OK;
3402 }
3403
3404 WERROR check_published_printers(void)
3405 {
3406         return WERR_OK;
3407 }
3408
3409 bool is_printer_published(Printer_entry *print_hnd, int snum,
3410                           struct GUID *guid)
3411 {
3412         return False;
3413 }
3414 #endif /* HAVE_ADS */
3415
3416 /****************************************************************************
3417  ***************************************************************************/
3418
3419 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3420 {
3421         NT_PRINTER_DATA *data;
3422         int             i;
3423         int             removed_keys = 0;
3424         int             empty_slot;
3425
3426         data = p2->data;
3427         empty_slot = data->num_keys;
3428
3429         if ( !key )
3430                 return WERR_INVALID_PARAM;
3431
3432         /* remove all keys */
3433
3434         if ( !strlen(key) ) {
3435
3436                 TALLOC_FREE( data );
3437
3438                 p2->data = NULL;
3439
3440                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3441                         p2->printername ));
3442
3443                 return WERR_OK;
3444         }
3445
3446         /* remove a specific key (and all subkeys) */
3447
3448         for ( i=0; i<data->num_keys; i++ ) {
3449                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3450                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3451                                 data->keys[i].name));
3452
3453                         TALLOC_FREE( data->keys[i].name );
3454                         TALLOC_FREE( data->keys[i].values );
3455
3456                         /* mark the slot as empty */
3457
3458                         ZERO_STRUCTP( &data->keys[i] );
3459                 }
3460         }
3461
3462         /* find the first empty slot */
3463
3464         for ( i=0; i<data->num_keys; i++ ) {
3465                 if ( !data->keys[i].name ) {
3466                         empty_slot = i;
3467                         removed_keys++;
3468                         break;
3469                 }
3470         }
3471
3472         if ( i == data->num_keys )
3473                 /* nothing was removed */
3474                 return WERR_INVALID_PARAM;
3475
3476         /* move everything down */
3477
3478         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3479                 if ( data->keys[i].name ) {
3480                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3481                         ZERO_STRUCTP( &data->keys[i] );
3482                         empty_slot++;
3483                         removed_keys++;
3484                 }
3485         }
3486
3487         /* update count */
3488
3489         data->num_keys -= removed_keys;
3490
3491         /* sanity check to see if anything is left */
3492
3493         if ( !data->num_keys ) {
3494                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3495
3496                 SAFE_FREE( data->keys );
3497                 ZERO_STRUCTP( data );
3498         }
3499
3500         return WERR_OK;
3501 }
3502
3503 /****************************************************************************
3504  ***************************************************************************/
3505
3506 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3507 {
3508         WERROR          result = WERR_OK;
3509         int             key_index;
3510
3511         /* we must have names on non-zero length */
3512
3513         if ( !key || !*key|| !value || !*value )
3514                 return WERR_INVALID_NAME;
3515
3516         /* find the printer key first */
3517
3518         key_index = lookup_printerkey( p2->data, key );
3519         if ( key_index == -1 )
3520                 return WERR_OK;
3521
3522         /* make sure the value exists so we can return the correct error code */
3523
3524         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3525                 return WERR_BADFILE;
3526
3527         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3528
3529         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3530                 key, value ));
3531
3532         return result;
3533 }
3534
3535 /****************************************************************************
3536  ***************************************************************************/
3537
3538 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3539                            uint32 type, uint8 *data, int real_len )
3540 {
3541         WERROR          result = WERR_OK;
3542         int             key_index;
3543
3544         /* we must have names on non-zero length */
3545
3546         if ( !key || !*key|| !value || !*value )
3547                 return WERR_INVALID_NAME;
3548
3549         /* find the printer key first */
3550
3551         key_index = lookup_printerkey( p2->data, key );
3552         if ( key_index == -1 )
3553                 key_index = add_new_printer_key( p2->data, key );
3554
3555         if ( key_index == -1 )
3556                 return WERR_NOMEM;
3557
3558         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3559                 type, data, real_len );
3560
3561         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3562                 key, value, type, real_len  ));
3563
3564         return result;
3565 }
3566
3567 /****************************************************************************
3568  ***************************************************************************/
3569
3570 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3571 {
3572         int             key_index;
3573
3574         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3575                 return NULL;
3576
3577         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3578                 key, value ));
3579
3580         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3581 }
3582
3583 /****************************************************************************
3584  Unpack a list of registry values frem the TDB
3585  ***************************************************************************/
3586
3587 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3588 {
3589         int             len = 0;
3590         uint32          type;
3591         fstring string;
3592         const char *valuename = NULL;
3593         const char *keyname = NULL;
3594         char            *str;
3595         int             size;
3596         uint8           *data_p;
3597         struct regval_blob      *regval_p;
3598         int             key_index;
3599
3600         /* add the "PrinterDriverData" key first for performance reasons */
3601
3602         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3603
3604         /* loop and unpack the rest of the registry values */
3605
3606         while ( True ) {
3607
3608                 /* check to see if there are any more registry values */
3609
3610                 regval_p = NULL;
3611                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3612                 if ( !regval_p )
3613                         break;
3614
3615                 /* unpack the next regval */
3616
3617                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3618                                   string,
3619                                   &type,
3620                                   &size,
3621                                   &data_p);
3622
3623                 /* lookup for subkey names which have a type of REG_NONE */
3624                 /* there's no data with this entry */
3625
3626                 if ( type == REG_NONE ) {
3627                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3628                                 add_new_printer_key( printer_data, string );
3629                         continue;
3630                 }
3631
3632                 /*
3633                  * break of the keyname from the value name.
3634                  * Valuenames can have embedded '\'s so be careful.
3635                  * only support one level of keys.  See the
3636                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3637                  * -- jerry
3638                  */
3639
3640                 str = strchr_m( string, '\\');
3641
3642                 /* Put in "PrinterDriverData" is no key specified */
3643
3644                 if ( !str ) {
3645                         keyname = SPOOL_PRINTERDATA_KEY;
3646                         valuename = string;
3647                 }
3648                 else {
3649                         *str = '\0';
3650                         keyname = string;
3651                         valuename = str+1;
3652                 }
3653
3654                 /* see if we need a new key */
3655
3656                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3657                         key_index = add_new_printer_key( printer_data, keyname );
3658
3659                 if ( key_index == -1 ) {
3660                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3661                                 keyname));
3662                         break;
3663                 }
3664
3665                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3666
3667                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3668                    Thanks to Martin Zielinski for the hint. */
3669
3670                 if ( type == REG_BINARY &&
3671                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3672                      strequal( valuename, "objectGUID" ) )
3673                 {
3674                         struct GUID guid;
3675
3676                         /* convert the GUID to a UNICODE string */
3677
3678                         memcpy( &guid, data_p, sizeof(struct GUID) );
3679
3680                         regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3681                                                valuename,
3682                                                GUID_string(talloc_tos(), &guid));
3683
3684                 } else {
3685                         /* add the value */
3686
3687                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3688                                              valuename, type, data_p,
3689                                              size );
3690                 }
3691
3692                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3693
3694         }
3695
3696         return len;
3697 }
3698
3699 /****************************************************************************
3700  ***************************************************************************/
3701
3702 static char *win_driver;
3703 static char *os2_driver;
3704
3705 static const char *get_win_driver(void)
3706 {
3707         if (win_driver == NULL) {
3708                 return "";
3709         }
3710         return win_driver;
3711 }
3712
3713 static const char *get_os2_driver(void)
3714 {
3715         if (os2_driver == NULL) {
3716                 return "";
3717         }
3718         return os2_driver;
3719 }
3720
3721 static bool set_driver_mapping(const char *from, const char *to)
3722 {
3723         SAFE_FREE(win_driver);
3724         SAFE_FREE(os2_driver);
3725
3726         win_driver = SMB_STRDUP(from);
3727         os2_driver = SMB_STRDUP(to);
3728
3729         if (win_driver == NULL || os2_driver == NULL) {
3730                 SAFE_FREE(win_driver);
3731                 SAFE_FREE(os2_driver);
3732                 return false;
3733         }
3734         return true;
3735 }
3736
3737 static void map_to_os2_driver(fstring drivername)
3738 {
3739         char *mapfile = lp_os2_driver_map();
3740         char **lines = NULL;
3741         int numlines = 0;
3742         int i;
3743
3744         if (!strlen(drivername))
3745                 return;
3746
3747         if (!*mapfile)
3748                 return;
3749
3750         if (strequal(drivername, get_win_driver())) {
3751                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3752                         drivername, get_os2_driver()));
3753                 fstrcpy(drivername, get_os2_driver());
3754                 return;
3755         }
3756
3757         lines = file_lines_load(mapfile, &numlines,0,NULL);
3758         if (numlines == 0 || lines == NULL) {
3759                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3760                 TALLOC_FREE(lines);
3761                 return;
3762         }
3763
3764         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3765
3766         for( i = 0; i < numlines; i++) {
3767                 char *nt_name = lines[i];
3768                 char *os2_name = strchr(nt_name,'=');
3769
3770                 if (!os2_name)
3771                         continue;
3772
3773                 *os2_name++ = 0;
3774
3775                 while (isspace(*nt_name))
3776                         nt_name++;
3777
3778                 if (!*nt_name || strchr("#;",*nt_name))
3779                         continue;
3780
3781                 {
3782                         int l = strlen(nt_name);
3783                         while (l && isspace(nt_name[l-1])) {
3784                                 nt_name[l-1] = 0;
3785                                 l--;
3786                         }
3787                 }
3788
3789                 while (isspace(*os2_name))
3790                         os2_name++;
3791
3792                 {
3793                         int l = strlen(os2_name);
3794                         while (l && isspace(os2_name[l-1])) {
3795                                 os2_name[l-1] = 0;
3796                                 l--;
3797                         }
3798                 }
3799
3800                 if (strequal(nt_name,drivername)) {
3801                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3802                         set_driver_mapping(drivername,os2_name);
3803                         fstrcpy(drivername,os2_name);
3804                         TALLOC_FREE(lines);
3805                         return;
3806                 }
3807         }
3808
3809         TALLOC_FREE(lines);
3810 }
3811
3812 /**
3813  * @internal
3814  *
3815  * @brief Map a Windows driver to a OS/2 driver.
3816  *
3817  * @param[in]  mem_ctx  The memory context to use.
3818  *
3819  * @param[in,out] pdrivername The drivername of Windows to remap.
3820  *
3821  * @return              WERR_OK on success, a corresponding WERROR on failure.
3822  */
3823 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3824 {
3825         const char *mapfile = lp_os2_driver_map();
3826         char **lines = NULL;
3827         const char *drivername;
3828         int numlines = 0;
3829         int i;
3830
3831         if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3832                 return WERR_INVALID_PARAMETER;
3833         }
3834
3835         drivername = *pdrivername;
3836
3837         if (mapfile[0] == '\0') {
3838                 return WERR_BADFILE;
3839         }
3840
3841         if (strequal(drivername, get_win_driver())) {
3842                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3843                         drivername, get_os2_driver()));
3844                 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3845                 if (drivername == NULL) {
3846                         return WERR_NOMEM;
3847                 }
3848                 *pdrivername = drivername;
3849                 return WERR_OK;
3850         }
3851
3852         lines = file_lines_load(mapfile, &numlines, 0, NULL);
3853         if (numlines == 0 || lines == NULL) {
3854                 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
3855                 TALLOC_FREE(lines);
3856                 return WERR_EMPTY;
3857         }
3858
3859         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3860
3861         for( i = 0; i < numlines; i++) {
3862                 char *nt_name = lines[i];
3863                 char *os2_name = strchr(nt_name, '=');
3864
3865                 if (os2_name == NULL) {
3866                         continue;
3867                 }
3868
3869                 *os2_name++ = '\0';
3870
3871                 while (isspace(*nt_name)) {
3872                         nt_name++;
3873                 }
3874
3875                 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
3876                         continue;
3877                 }
3878
3879                 {
3880                         int l = strlen(nt_name);
3881                         while (l && isspace(nt_name[l - 1])) {
3882                                 nt_name[l - 1] = 0;
3883                                 l--;
3884                         }
3885                 }
3886
3887                 while (isspace(*os2_name)) {
3888                         os2_name++;
3889                 }
3890
3891                 {
3892                         int l = strlen(os2_name);
3893                         while (l && isspace(os2_name[l-1])) {
3894                                 os2_name[l-1] = 0;
3895                                 l--;
3896                         }
3897                 }
3898
3899                 if (strequal(nt_name, drivername)) {
3900                         DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
3901                         set_driver_mapping(drivername, os2_name);
3902                         drivername = talloc_strdup(mem_ctx, os2_name);
3903                         TALLOC_FREE(lines);
3904                         if (drivername == NULL) {
3905                                 return WERR_NOMEM;
3906                         }
3907                         *pdrivername = drivername;
3908                         return WERR_OK;
3909                 }
3910         }
3911
3912         TALLOC_FREE(lines);
3913         return WERR_OK;
3914 }
3915
3916 /****************************************************************************
3917  Get a default printer info 2 struct.
3918 ****************************************************************************/
3919
3920 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3921                                 const char *servername,
3922                                 const char* sharename,
3923                                 bool get_loc_com)
3924 {
3925         int snum = lp_servicenumber(sharename);
3926         WERROR result;
3927
3928         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3929         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3930                 servername, sharename);
3931         fstrcpy(info->sharename, sharename);
3932         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3933
3934         /* by setting the driver name to an empty string, a local NT admin
3935            can now run the **local** APW to install a local printer driver
3936            for a Samba shared printer in 2.2.  Without this, drivers **must** be
3937            installed on the Samba server for NT clients --jerry */
3938 #if 0   /* JERRY --do not uncomment-- */
3939         if (!*info->drivername)
3940                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3941 #endif
3942
3943
3944         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3945
3946         strlcpy(info->comment, "", sizeof(info->comment));
3947         fstrcpy(info->printprocessor, "winprint");
3948         fstrcpy(info->datatype, "RAW");
3949
3950 #ifdef HAVE_CUPS
3951         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3952                 /* Pull the location and comment strings from cups if we don't
3953                    already have one */
3954                 if ( !strlen(info->location) || !strlen(info->comment) ) {
3955                         char *comment = NULL;
3956                         char *location = NULL;
3957                         if (cups_pull_comment_location(info, info->sharename,
3958                                                        &comment, &location)) {
3959                                 strlcpy(info->comment, comment, sizeof(info->comment));
3960                                 fstrcpy(info->location, location);
3961                                 TALLOC_FREE(comment);
3962                                 TALLOC_FREE(location);
3963                         }
3964                 }
3965         }
3966 #endif
3967
3968         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3969
3970         info->starttime = 0; /* Minutes since 12:00am GMT */
3971         info->untiltime = 0; /* Minutes since 12:00am GMT */
3972         info->priority = 1;
3973         info->default_priority = 1;
3974         info->setuptime = (uint32)time(NULL);
3975
3976         /*
3977          * I changed this as I think it is better to have a generic
3978          * DEVMODE than to crash Win2k explorer.exe   --jerry
3979          * See the HP Deskjet 990c Win2k drivers for an example.
3980          *
3981          * However the default devmode appears to cause problems
3982          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3983          * the "default devmode" parameter   --jerry 22/01/2002
3984          */
3985
3986         if (lp_default_devmode(snum)) {
3987                 result = spoolss_create_default_devmode(info,
3988                                                         info->printername,
3989                                                         &info->devmode);
3990                 if (!W_ERROR_IS_OK(result)) {
3991                         goto fail;
3992                 }
3993         } else {
3994                 info->devmode = NULL;
3995         }
3996
3997         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3998                 goto fail;
3999         }
4000
4001         info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4002         if (!info->data) {
4003                 goto fail;
4004         }
4005
4006         add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4007
4008         return WERR_OK;
4009
4010 fail:
4011         TALLOC_FREE(info->devmode);
4012
4013         return WERR_ACCESS_DENIED;
4014 }
4015
4016 /****************************************************************************
4017 ****************************************************************************/
4018
4019 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4020                                 const char *servername,
4021                                 const char *sharename,
4022                                 bool get_loc_com)
4023 {
4024         int len = 0;
4025         int snum = lp_servicenumber(sharename);
4026         TDB_DATA kbuf, dbuf;
4027         fstring printername;
4028         char *comment = NULL;
4029         WERROR result;
4030
4031         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4032
4033         dbuf = tdb_fetch(tdb_printers, kbuf);
4034         if (!dbuf.dptr) {
4035                 return get_a_printer_2_default(info, servername,
4036                                         sharename, get_loc_com);
4037         }
4038
4039         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4040                         &info->attributes,
4041                         &info->priority,
4042                         &info->default_priority,
4043                         &info->starttime,
4044                         &info->untiltime,
4045                         &info->status,
4046                         &info->cjobs,
4047                         &info->averageppm,
4048                         &info->changeid,
4049                         &info->c_setprinter,
4050                         &info->setuptime,
4051                         info->servername,
4052                         info->printername,
4053                         info->sharename,
4054                         info->portname,
4055                         info->drivername,
4056                         &comment,
4057                         info->location,
4058                         info->sepfile,
4059                         info->printprocessor,
4060                         info->datatype,
4061                         info->parameters);
4062
4063         if (comment) {
4064                 strlcpy(info->comment, comment, sizeof(info->comment));
4065                 SAFE_FREE(comment);
4066         }
4067
4068         /* Samba has to have shared raw drivers. */
4069         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4070         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4071
4072         /* Restore the stripped strings. */
4073         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4074
4075         if ( lp_force_printername(snum) ) {
4076                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4077         } else {
4078                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4079         }
4080
4081         fstrcpy(info->printername, printername);
4082
4083 #ifdef HAVE_CUPS
4084         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4085                 /* Pull the location and comment strings from cups if we don't
4086                    already have one */
4087                 if ( !strlen(info->location) || !strlen(info->comment) ) {
4088                         char *location = NULL;
4089                         comment = NULL;
4090                         if (cups_pull_comment_location(info, info->sharename,
4091                                                        &comment, &location)) {
4092                                 strlcpy(info->comment, comment, sizeof(info->comment));
4093                                 fstrcpy(info->location, location);
4094                                 TALLOC_FREE(comment);
4095                                 TALLOC_FREE(location);
4096                         }
4097                 }
4098         }
4099 #endif
4100
4101         len += unpack_devicemode(info, dbuf.dptr+len,
4102                                         dbuf.dsize-len,
4103                                         &info->devmode);
4104
4105         /*
4106          * Some client drivers freak out if there is a NULL devmode
4107          * (probably the driver is not checking before accessing
4108          * the devmode pointer)   --jerry
4109          *
4110          * See comments in get_a_printer_2_default()
4111          */
4112
4113         if (lp_default_devmode(snum) && !info->devmode) {
4114                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4115                         printername));
4116                 result = spoolss_create_default_devmode(info, printername,
4117                                                         &info->devmode);
4118                 if (!W_ERROR_IS_OK(result)) {
4119                         goto done;
4120                 }
4121         }
4122
4123         if (info->devmode) {
4124                 info->devmode->devicename = talloc_strdup(info->devmode,
4125                                                           info->printername);
4126                 if (!info->devmode->devicename) {
4127                         result = WERR_NOMEM;
4128                         goto done;
4129                 }
4130         }
4131
4132         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4133                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4134                 result = WERR_NOMEM;
4135                 goto done;
4136         }
4137         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4138
4139         /* This will get the current RPC talloc context, but we should be
4140            passing this as a parameter... fixme... JRA ! */
4141
4142         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4143                 result = WERR_NOMEM;
4144                 goto done;
4145         }
4146
4147         /* Fix for OS/2 drivers. */
4148
4149         if (get_remote_arch() == RA_OS2) {
4150                 map_to_os2_driver(info->drivername);
4151         }
4152
4153         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4154                  sharename, info->printername, info->drivername));
4155
4156         result = WERR_OK;
4157
4158 done:
4159         SAFE_FREE(dbuf.dptr);
4160         return result;
4161 }
4162
4163 /****************************************************************************
4164  Debugging function, dump at level 6 the struct in the logs.
4165 ****************************************************************************/
4166 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4167 {
4168         uint32 result;
4169         NT_PRINTER_INFO_LEVEL_2 *info2;
4170
4171         DEBUG(106,("Dumping printer at level [%d]\n", level));
4172
4173         switch (level) {
4174                 case 2:
4175                 {
4176                         if (printer->info_2 == NULL)
4177                                 result=5;
4178                         else
4179                         {
4180                                 info2=printer->info_2;
4181
4182                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4183                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4184                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4185                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4186                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4187                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4188                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4189                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4190                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4191                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4192                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4193
4194                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4195                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4196                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4197                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4198                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4199                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4200                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4201                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4202                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4203                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4204                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4205                                 result=0;
4206                         }
4207                         break;
4208                 }
4209                 default:
4210                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4211                         result=1;
4212                         break;
4213         }
4214
4215         return result;
4216 }
4217
4218 /****************************************************************************
4219  Update the changeid time.
4220  This is SO NASTY as some drivers need this to change, others need it
4221  static. This value will change every second, and I must hope that this
4222  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4223  UTAH ! JRA.
4224 ****************************************************************************/
4225
4226 static uint32 rev_changeid(void)
4227 {
4228         struct timeval tv;
4229
4230         get_process_uptime(&tv);
4231
4232 #if 1   /* JERRY */
4233         /* Return changeid as msec since spooler restart */
4234         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4235 #else
4236         /*
4237          * This setting seems to work well but is too untested
4238          * to replace the above calculation.  Left in for experiementation
4239          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4240          */
4241         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4242 #endif
4243 }
4244
4245
4246 /*
4247  * The function below are the high level ones.
4248  * only those ones must be called from the spoolss code.
4249  * JFM.
4250  */
4251
4252 /****************************************************************************
4253  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4254 ****************************************************************************/
4255
4256 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4257 {
4258         WERROR result;
4259
4260         dump_a_printer(printer, level);
4261
4262         switch (level) {
4263                 case 2:
4264                 {
4265                         /*
4266                          * Update the changestamp.  Emperical tests show that the
4267                          * ChangeID is always updated,but c_setprinter is
4268                          *  global spooler variable (not per printer).
4269                          */
4270
4271                         /* ChangeID **must** be increasing over the lifetime
4272                            of client's spoolss service in order for the
4273                            client's cache to show updates */
4274
4275                         printer->info_2->changeid = rev_changeid();
4276
4277                         /*
4278                          * Because one day someone will ask:
4279                          * NT->NT       An admin connection to a remote
4280                          *              printer show changes imeediately in
4281                          *              the properities dialog
4282                          *
4283                          *              A non-admin connection will only show the
4284                          *              changes after viewing the properites page
4285                          *              2 times.  Seems to be related to a
4286                          *              race condition in the client between the spooler
4287                          *              updating the local cache and the Explorer.exe GUI
4288                          *              actually displaying the properties.
4289                          *
4290                          *              This is fixed in Win2k.  admin/non-admin
4291                          *              connections both display changes immediately.
4292                          *
4293                          * 14/12/01     --jerry
4294                          */
4295
4296                         result=update_a_printer_2(printer->info_2);
4297                         break;
4298                 }
4299                 default:
4300                         result=WERR_UNKNOWN_LEVEL;
4301                         break;
4302         }
4303
4304         return result;
4305 }
4306
4307 /****************************************************************************
4308  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4309
4310  Previously the code had a memory allocation problem because it always
4311  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4312  as a long as the original handle is open.  So if the client made a lot
4313  of getprinter[data]() calls, the memory usage would climb.  Now we use
4314  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4315  still use the Printer_entry->ctx for maintaining the cache copy though
4316  since that object must live as long as the handle by definition.
4317                                                     --jerry
4318
4319 ****************************************************************************/
4320
4321 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4322                         const char *sharename, bool get_loc_com)
4323 {
4324         WERROR result;
4325         fstring servername;
4326
4327         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4328
4329         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4330                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4331                 return WERR_NOMEM;
4332         }
4333
4334         switch (level) {
4335                 case 2:
4336                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4337                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4338                                 TALLOC_FREE( *pp_printer );
4339                                 return WERR_NOMEM;
4340                         }
4341
4342                         if ( print_hnd )
4343                                 fstrcpy( servername, print_hnd->servername );
4344                         else {
4345                                 fstrcpy( servername, "%L" );
4346                                 standard_sub_basic( "", "", servername,
4347                                                     sizeof(servername)-1 );
4348                         }
4349
4350                         result = get_a_printer_2( (*pp_printer)->info_2,
4351                                         servername, sharename, get_loc_com);
4352
4353                         /* we have a new printer now.  Save it with this handle */
4354
4355                         if ( !W_ERROR_IS_OK(result) ) {
4356                                 TALLOC_FREE( *pp_printer );
4357                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4358                                         sharename, (unsigned int)level, win_errstr(result)));
4359                                 return result;
4360                         }
4361
4362                         dump_a_printer( *pp_printer, level);
4363
4364                         break;
4365
4366                 default:
4367                         TALLOC_FREE( *pp_printer );
4368                         return WERR_UNKNOWN_LEVEL;
4369         }
4370
4371         return WERR_OK;
4372 }
4373
4374 WERROR get_a_printer( Printer_entry *print_hnd,
4375                         NT_PRINTER_INFO_LEVEL **pp_printer,
4376                         uint32 level,
4377                         const char *sharename)
4378 {
4379         return get_a_printer_internal(print_hnd, pp_printer, level,
4380                                         sharename, true);
4381 }
4382
4383 WERROR get_a_printer_search( Printer_entry *print_hnd,
4384                         NT_PRINTER_INFO_LEVEL **pp_printer,
4385                         uint32 level,
4386                         const char *sharename)
4387 {
4388         return get_a_printer_internal(print_hnd, pp_printer, level,
4389                                         sharename, false);
4390 }
4391
4392 /****************************************************************************
4393  Deletes a NT_PRINTER_INFO_LEVEL struct.
4394 ****************************************************************************/
4395
4396 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4397 {
4398         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4399
4400         if ( !printer )
4401                 return 0;
4402
4403         switch (level) {
4404                 case 2:
4405                         TALLOC_FREE(printer->info_2);
4406                         break;
4407
4408                 default:
4409                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4410                         return 1;
4411         }
4412
4413         TALLOC_FREE(*pp_printer);
4414
4415         return 0;
4416 }
4417
4418 /****************************************************************************
4419 ****************************************************************************/
4420
4421 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4422                               struct spoolss_DriverInfo8 *_info8)
4423 {
4424         struct spoolss_DriverInfo8 info8;
4425
4426         ZERO_STRUCT(info8);
4427
4428         switch (r->level) {
4429         case 3:
4430                 info8.version           = r->info.info3->version;
4431                 info8.driver_name       = r->info.info3->driver_name;
4432                 info8.architecture      = r->info.info3->architecture;
4433                 info8.driver_path       = r->info.info3->driver_path;
4434                 info8.data_file         = r->info.info3->data_file;
4435                 info8.config_file       = r->info.info3->config_file;
4436                 info8.help_file         = r->info.info3->help_file;
4437                 info8.monitor_name      = r->info.info3->monitor_name;
4438                 info8.default_datatype  = r->info.info3->default_datatype;
4439                 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4440                         info8.dependent_files   = r->info.info3->dependent_files->string;
4441                 }
4442                 break;
4443         case 6:
4444                 info8.version           = r->info.info6->version;
4445                 info8.driver_name       = r->info.info6->driver_name;
4446                 info8.architecture      = r->info.info6->architecture;
4447                 info8.driver_path       = r->info.info6->driver_path;
4448                 info8.data_file         = r->info.info6->data_file;
4449                 info8.config_file       = r->info.info6->config_file;
4450                 info8.help_file         = r->info.info6->help_file;
4451                 info8.monitor_name      = r->info.info6->monitor_name;
4452                 info8.default_datatype  = r->info.info6->default_datatype;
4453                 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4454                         info8.dependent_files   = r->info.info6->dependent_files->string;
4455                 }
4456                 info8.driver_date       = r->info.info6->driver_date;
4457                 info8.driver_version    = r->info.info6->driver_version;
4458                 info8.manufacturer_name = r->info.info6->manufacturer_name;
4459                 info8.manufacturer_url  = r->info.info6->manufacturer_url;
4460                 info8.hardware_id       = r->info.info6->hardware_id;
4461                 info8.provider          = r->info.info6->provider;
4462                 break;
4463         case 8:
4464                 info8.version           = r->info.info8->version;
4465                 info8.driver_name       = r->info.info8->driver_name;
4466                 info8.architecture      = r->info.info8->architecture;
4467                 info8.driver_path       = r->info.info8->driver_path;
4468                 info8.data_file         = r->info.info8->data_file;
4469                 info8.config_file       = r->info.info8->config_file;
4470                 info8.help_file         = r->info.info8->help_file;
4471                 info8.monitor_name      = r->info.info8->monitor_name;
4472                 info8.default_datatype  = r->info.info8->default_datatype;
4473                 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4474                         info8.dependent_files   = r->info.info8->dependent_files->string;
4475                 }
4476                 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4477                         info8.previous_names    = r->info.info8->previous_names->string;
4478                 }
4479                 info8.driver_date       = r->info.info8->driver_date;
4480                 info8.driver_version    = r->info.info8->driver_version;
4481                 info8.manufacturer_name = r->info.info8->manufacturer_name;
4482                 info8.manufacturer_url  = r->info.info8->manufacturer_url;
4483                 info8.hardware_id       = r->info.info8->hardware_id;
4484                 info8.provider          = r->info.info8->provider;
4485                 info8.print_processor   = r->info.info8->print_processor;
4486                 info8.vendor_setup      = r->info.info8->vendor_setup;
4487                 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4488                         info8.color_profiles = r->info.info8->color_profiles->string;
4489                 }
4490                 info8.inf_path          = r->info.info8->inf_path;
4491                 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4492                 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4493                         info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4494                 }
4495                 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4496                 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4497                 break;
4498         default:
4499                 return false;
4500         }
4501
4502         *_info8 = info8;
4503
4504         return true;
4505 }
4506
4507
4508 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4509                               struct spoolss_AddDriverInfoCtr *r,
4510                               char **driver_name,
4511                               uint32_t *version)
4512 {
4513         struct spoolss_DriverInfo8 info8;
4514
4515         ZERO_STRUCT(info8);
4516
4517         DEBUG(10,("adding a printer at level [%d]\n", r->level));
4518
4519         if (!driver_info_ctr_to_info8(r, &info8)) {
4520                 return -1;
4521         }
4522
4523         *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4524         if (!*driver_name) {
4525                 return -1;
4526         }
4527         *version = info8.version;
4528
4529         return add_a_printer_driver_8(&info8);
4530 }
4531
4532 /****************************************************************************
4533 ****************************************************************************/
4534
4535 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4536                             struct spoolss_DriverInfo8 **driver,
4537                             const char *drivername, const char *architecture,
4538                             uint32_t version)
4539 {
4540         WERROR result;
4541         struct spoolss_DriverInfo3 info3;
4542         struct spoolss_DriverInfo8 *info8;
4543
4544         ZERO_STRUCT(info3);
4545
4546         /* Sometime we just want any version of the driver */
4547
4548         if (version == DRIVER_ANY_VERSION) {
4549                 /* look for Win2k first and then for NT4 */
4550                 result = get_a_printer_driver_3(mem_ctx,
4551                                                 &info3,
4552                                                 drivername,
4553                                                 architecture, 3);
4554                 if (!W_ERROR_IS_OK(result)) {
4555                         result = get_a_printer_driver_3(mem_ctx,
4556                                                         &info3,
4557                                                         drivername,
4558                                                         architecture, 2);
4559                 }
4560         } else {
4561                 result = get_a_printer_driver_3(mem_ctx,
4562                                                 &info3,
4563                                                 drivername,
4564                                                 architecture,
4565                                                 version);
4566         }
4567
4568         if (!W_ERROR_IS_OK(result)) {
4569                 return result;
4570         }
4571
4572         info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4573         if (!info8) {
4574                 return WERR_NOMEM;
4575         }
4576
4577         info8->version          = info3.version;
4578         info8->driver_name      = info3.driver_name;
4579         info8->architecture     = info3.architecture;
4580         info8->driver_path      = info3.driver_path;
4581         info8->data_file        = info3.data_file;
4582         info8->config_file      = info3.config_file;
4583         info8->help_file        = info3.help_file;
4584         info8->dependent_files  = info3.dependent_files;
4585         info8->monitor_name     = info3.monitor_name;
4586         info8->default_datatype = info3.default_datatype;
4587
4588         *driver = info8;
4589
4590         return WERR_OK;
4591 }
4592
4593 /****************************************************************************
4594 ****************************************************************************/
4595
4596 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4597 {
4598         talloc_free(driver);
4599         return 0;
4600 }
4601
4602
4603 /****************************************************************************
4604   Determine whether or not a particular driver is currently assigned
4605   to a printer
4606 ****************************************************************************/
4607
4608 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4609 {
4610         int snum;
4611         int n_services = lp_numservices();
4612         NT_PRINTER_INFO_LEVEL *printer = NULL;
4613         bool in_use = False;
4614
4615         if (!r) {
4616                 return false;
4617         }
4618
4619         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4620
4621         /* loop through the printers.tdb and check for the drivername */
4622
4623         for (snum=0; snum<n_services && !in_use; snum++) {
4624                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4625                         continue;
4626
4627                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4628                         continue;
4629
4630                 if (strequal(r->driver_name, printer->info_2->drivername))
4631                         in_use = True;
4632
4633                 free_a_printer( &printer, 2 );
4634         }
4635
4636         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4637
4638         if ( in_use ) {
4639                 struct spoolss_DriverInfo8 *d;
4640                 WERROR werr;
4641
4642                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4643
4644                 /* we can still remove the driver if there is one of
4645                    "Windows NT x86" version 2 or 3 left */
4646
4647                 if (!strequal("Windows NT x86", r->architecture)) {
4648                         werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4649                 }
4650                 else {
4651                         switch (r->version) {
4652                         case 2:
4653                                 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4654                                 break;
4655                         case 3:
4656                                 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4657                                 break;
4658                         default:
4659                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4660                                         r->version));
4661                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4662                                 break;
4663                         }
4664                 }
4665
4666                 /* now check the error code */
4667
4668                 if ( W_ERROR_IS_OK(werr) ) {
4669                         /* it's ok to remove the driver, we have other architctures left */
4670                         in_use = False;
4671                         free_a_printer_driver(d);
4672                 }
4673         }
4674
4675         /* report that the driver is not in use by default */
4676
4677         return in_use;
4678 }
4679
4680
4681 /**********************************************************************
4682  Check to see if a ogiven file is in use by *info
4683  *********************************************************************/
4684
4685 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4686 {
4687         int i = 0;
4688
4689         if ( !info )
4690                 return False;
4691
4692         /* mz: skip files that are in the list but already deleted */
4693         if (!file || !file[0]) {
4694                 return false;
4695         }
4696
4697         if (strequal(file, info->driver_path))
4698                 return True;
4699
4700         if (strequal(file, info->data_file))
4701                 return True;
4702
4703         if (strequal(file, info->config_file))
4704                 return True;
4705
4706         if (strequal(file, info->help_file))
4707                 return True;
4708
4709         /* see of there are any dependent files to examine */
4710
4711         if (!info->dependent_files)
4712                 return False;
4713
4714         while (info->dependent_files[i] && *info->dependent_files[i]) {
4715                 if (strequal(file, info->dependent_files[i]))
4716                         return True;
4717                 i++;
4718         }
4719
4720         return False;
4721
4722 }
4723
4724 /**********************************************************************
4725  Utility function to remove the dependent file pointed to by the
4726  input parameter from the list
4727  *********************************************************************/
4728
4729 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4730 {
4731
4732         /* bump everything down a slot */
4733
4734         while (files && files[idx+1]) {
4735                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4736                 idx++;
4737         }
4738
4739         files[idx] = NULL;
4740
4741         return;
4742 }
4743
4744 /**********************************************************************
4745  Check if any of the files used by src are also used by drv
4746  *********************************************************************/
4747
4748 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4749                                    struct spoolss_DriverInfo8 *src,
4750                                    const struct spoolss_DriverInfo8 *drv)
4751 {
4752         bool    in_use = False;
4753         int     i = 0;
4754
4755         if ( !src || !drv )
4756                 return False;
4757
4758         /* check each file.  Remove it from the src structure if it overlaps */
4759
4760         if (drv_file_in_use(src->driver_path, drv)) {
4761                 in_use = True;
4762                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4763                 src->driver_path = talloc_strdup(mem_ctx, "");
4764                 if (!src->driver_path) { return false; }
4765         }
4766
4767         if (drv_file_in_use(src->data_file, drv)) {
4768                 in_use = True;
4769                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4770                 src->data_file = talloc_strdup(mem_ctx, "");
4771                 if (!src->data_file) { return false; }
4772         }
4773
4774         if (drv_file_in_use(src->config_file, drv)) {
4775                 in_use = True;
4776                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4777                 src->config_file = talloc_strdup(mem_ctx, "");
4778                 if (!src->config_file) { return false; }
4779         }
4780
4781         if (drv_file_in_use(src->help_file, drv)) {
4782                 in_use = True;
4783                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4784                 src->help_file = talloc_strdup(mem_ctx, "");
4785                 if (!src->help_file) { return false; }
4786         }
4787
4788         /* are there any dependentfiles to examine? */
4789
4790         if (!src->dependent_files)
4791                 return in_use;
4792
4793         while (src->dependent_files[i] && *src->dependent_files[i]) {
4794                 if (drv_file_in_use(src->dependent_files[i], drv)) {
4795                         in_use = True;
4796                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4797                         trim_dependent_file(mem_ctx, src->dependent_files, i);
4798                 } else
4799                         i++;
4800         }
4801
4802         return in_use;
4803 }
4804
4805 /****************************************************************************
4806   Determine whether or not a particular driver files are currently being
4807   used by any other driver.
4808
4809   Return value is True if any files were in use by other drivers
4810   and False otherwise.
4811
4812   Upon return, *info has been modified to only contain the driver files
4813   which are not in use
4814
4815   Fix from mz:
4816
4817   This needs to check all drivers to ensure that all files in use
4818   have been removed from *info, not just the ones in the first
4819   match.
4820 ****************************************************************************/
4821
4822 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4823                                  struct spoolss_DriverInfo8 *info)
4824 {
4825         int                             i;
4826         int                             ndrivers;
4827         uint32                          version;
4828         fstring                         *list = NULL;
4829         struct spoolss_DriverInfo8      *driver;
4830         bool in_use = false;
4831
4832         if ( !info )
4833                 return False;
4834
4835         version = info->version;
4836
4837         /* loop over all driver versions */
4838
4839         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4840
4841         /* get the list of drivers */
4842
4843         list = NULL;
4844         ndrivers = get_ntdrivers(&list, info->architecture, version);
4845
4846         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4847                 ndrivers, info->architecture, version));
4848
4849         /* check each driver for overlap in files */
4850
4851         for (i=0; i<ndrivers; i++) {
4852                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4853
4854                 driver = NULL;
4855
4856                 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4857                         SAFE_FREE(list);
4858                         return True;
4859                 }
4860
4861                 /* check if d2 uses any files from d1 */
4862                 /* only if this is a different driver than the one being deleted */
4863
4864                 if (!strequal(info->driver_name, driver->driver_name)) {
4865                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4866                                 /* mz: Do not instantly return -
4867                                  * we need to ensure this file isn't
4868                                  * also in use by other drivers. */
4869                                 in_use = true;
4870                         }
4871                 }
4872
4873                 free_a_printer_driver(driver);
4874         }
4875
4876         SAFE_FREE(list);
4877
4878         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4879
4880         return in_use;
4881 }
4882
4883 static NTSTATUS driver_unlink_internals(connection_struct *conn,
4884                                         const char *name)
4885 {
4886         struct smb_filename *smb_fname = NULL;
4887         NTSTATUS status;
4888
4889         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
4890             &smb_fname);
4891         if (!NT_STATUS_IS_OK(status)) {
4892                 return status;
4893         }
4894
4895         status = unlink_internals(conn, NULL, 0, smb_fname, false);
4896
4897         TALLOC_FREE(smb_fname);
4898         return status;
4899 }
4900
4901 /****************************************************************************
4902   Actually delete the driver files.  Make sure that
4903   printer_driver_files_in_use() return False before calling
4904   this.
4905 ****************************************************************************/
4906
4907 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
4908                                 const struct spoolss_DriverInfo8 *r)
4909 {
4910         int i = 0;
4911         char *s;
4912         const char *file;
4913         connection_struct *conn;
4914         NTSTATUS nt_status;
4915         char *oldcwd;
4916         fstring printdollar;
4917         int printdollar_snum;
4918         bool ret = false;
4919
4920         if (!r) {
4921                 return false;
4922         }
4923
4924         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
4925                 r->driver_name, r->version));
4926
4927         fstrcpy(printdollar, "print$");
4928
4929         printdollar_snum = find_service(printdollar);
4930         if (printdollar_snum == -1) {
4931                 return false;
4932         }
4933
4934         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
4935                                        lp_pathname(printdollar_snum),
4936                                        rpc_pipe->server_info, &oldcwd);
4937         if (!NT_STATUS_IS_OK(nt_status)) {
4938                 DEBUG(0,("delete_driver_files: create_conn_struct "
4939                          "returned %s\n", nt_errstr(nt_status)));
4940                 return false;
4941         }
4942
4943         if ( !CAN_WRITE(conn) ) {
4944                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4945                 goto fail;
4946         }
4947
4948         /* now delete the files; must strip the '\print$' string from
4949            fron of path                                                */
4950
4951         if (r->driver_path && r->driver_path[0]) {
4952                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
4953                         file = s;
4954                         DEBUG(10,("deleting driverfile [%s]\n", s));
4955                         driver_unlink_internals(conn, file);
4956                 }
4957         }
4958
4959         if (r->config_file && r->config_file[0]) {
4960                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
4961                         file = s;
4962                         DEBUG(10,("deleting configfile [%s]\n", s));
4963                         driver_unlink_internals(conn, file);
4964                 }
4965         }
4966
4967         if (r->data_file && r->data_file[0]) {
4968                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
4969                         file = s;
4970                         DEBUG(10,("deleting datafile [%s]\n", s));
4971                         driver_unlink_internals(conn, file);
4972                 }
4973         }
4974
4975         if (r->help_file && r->help_file[0]) {
4976                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
4977                         file = s;
4978                         DEBUG(10,("deleting helpfile [%s]\n", s));
4979                         driver_unlink_internals(conn, file);
4980                 }
4981         }
4982
4983         /* check if we are done removing files */
4984
4985         if (r->dependent_files) {
4986                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
4987                         char *p;
4988
4989                         /* bypass the "\print$" portion of the path */
4990
4991                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
4992                                 file = p;
4993                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4994                                 driver_unlink_internals(conn, file);
4995                         }
4996
4997                         i++;
4998                 }
4999         }
5000
5001         goto done;
5002  fail:
5003         ret = false;
5004  done:
5005         if (conn != NULL) {
5006                 vfs_ChDir(conn, oldcwd);
5007                 conn_free(conn);
5008         }
5009         return ret;
5010 }
5011
5012 /****************************************************************************
5013  Remove a printer driver from the TDB.  This assumes that the the driver was
5014  previously looked up.
5015  ***************************************************************************/
5016
5017 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5018                              const struct spoolss_DriverInfo8 *r,
5019                              uint32 version, bool delete_files )
5020 {
5021         char *key = NULL;
5022         const char     *arch;
5023         TDB_DATA        dbuf;
5024
5025         /* delete the tdb data first */
5026
5027         arch = get_short_archi(r->architecture);
5028         if (!arch) {
5029                 return WERR_UNKNOWN_PRINTER_DRIVER;
5030         }
5031         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5032                         arch, version, r->driver_name) < 0) {
5033                 return WERR_NOMEM;
5034         }
5035
5036         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5037                 key, delete_files ? "TRUE" : "FALSE" ));
5038
5039         /* check if the driver actually exists for this environment */
5040
5041         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5042         if ( !dbuf.dptr ) {
5043                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5044                 SAFE_FREE(key);
5045                 return WERR_UNKNOWN_PRINTER_DRIVER;
5046         }
5047
5048         SAFE_FREE( dbuf.dptr );
5049
5050         /* ok... the driver exists so the delete should return success */
5051
5052         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5053                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5054                 SAFE_FREE(key);
5055                 return WERR_ACCESS_DENIED;
5056         }
5057
5058         /*
5059          * now delete any associated files if delete_files == True
5060          * even if this part failes, we return succes because the
5061          * driver doesn not exist any more
5062          */
5063
5064         if ( delete_files )
5065                 delete_driver_files(rpc_pipe, r);
5066
5067         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5068         SAFE_FREE(key);
5069
5070         return WERR_OK;
5071 }
5072
5073 /****************************************************************************
5074  Store a security desc for a printer.
5075 ****************************************************************************/
5076
5077 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5078 {
5079         struct sec_desc_buf *new_secdesc_ctr = NULL;
5080         struct sec_desc_buf *old_secdesc_ctr = NULL;
5081         TALLOC_CTX *mem_ctx = NULL;
5082         TDB_DATA kbuf;
5083         TDB_DATA dbuf;
5084         DATA_BLOB blob;
5085         WERROR status;
5086         NTSTATUS nt_status;
5087
5088         mem_ctx = talloc_init("nt_printing_setsec");
5089         if (mem_ctx == NULL)
5090                 return WERR_NOMEM;
5091
5092         /* The old owner and group sids of the security descriptor are not
5093            present when new ACEs are added or removed by changing printer
5094            permissions through NT.  If they are NULL in the new security
5095            descriptor then copy them over from the old one. */
5096
5097         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5098                 struct dom_sid *owner_sid, *group_sid;
5099                 struct security_acl *dacl, *sacl;
5100                 struct security_descriptor *psd = NULL;
5101                 size_t size;
5102
5103                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5104                         status = WERR_NOMEM;
5105                         goto out;
5106                 }
5107
5108                 /* Pick out correct owner and group sids */
5109
5110                 owner_sid = secdesc_ctr->sd->owner_sid ?
5111                         secdesc_ctr->sd->owner_sid :
5112                         old_secdesc_ctr->sd->owner_sid;
5113
5114                 group_sid = secdesc_ctr->sd->group_sid ?
5115                         secdesc_ctr->sd->group_sid :
5116                         old_secdesc_ctr->sd->group_sid;
5117
5118                 dacl = secdesc_ctr->sd->dacl ?
5119                         secdesc_ctr->sd->dacl :
5120                         old_secdesc_ctr->sd->dacl;
5121
5122                 sacl = secdesc_ctr->sd->sacl ?
5123                         secdesc_ctr->sd->sacl :
5124                         old_secdesc_ctr->sd->sacl;
5125
5126                 /* Make a deep copy of the security descriptor */
5127
5128                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5129                                     owner_sid, group_sid,
5130                                     sacl,
5131                                     dacl,
5132                                     &size);
5133
5134                 if (!psd) {
5135                         status = WERR_NOMEM;
5136                         goto out;
5137                 }
5138
5139                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5140         }
5141
5142         if (!new_secdesc_ctr) {
5143                 new_secdesc_ctr = secdesc_ctr;
5144         }
5145
5146         /* Store the security descriptor in a tdb */
5147
5148         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5149                                           &blob.data, &blob.length);
5150         if (!NT_STATUS_IS_OK(nt_status)) {
5151                 status = ntstatus_to_werror(nt_status);
5152                 goto out;
5153         }
5154
5155         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5156
5157         dbuf.dptr = (unsigned char *)blob.data;
5158         dbuf.dsize = blob.length;
5159
5160         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5161                 status = WERR_OK;
5162         } else {
5163                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5164                 status = WERR_BADFUNC;
5165         }
5166
5167         /* Free malloc'ed memory */
5168         talloc_free(blob.data);
5169
5170  out:
5171
5172         if (mem_ctx)
5173                 talloc_destroy(mem_ctx);
5174         return status;
5175 }
5176
5177 /****************************************************************************
5178  Construct a default security descriptor buffer for a printer.
5179 ****************************************************************************/
5180
5181 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5182 {
5183         struct security_ace ace[7];     /* max number of ace entries */
5184         int i = 0;
5185         uint32_t sa;
5186         struct security_acl *psa = NULL;
5187         struct sec_desc_buf *sdb = NULL;
5188         struct security_descriptor *psd = NULL;
5189         struct dom_sid adm_sid;
5190         size_t sd_size;
5191
5192         /* Create an ACE where Everyone is allowed to print */
5193
5194         sa = PRINTER_ACE_PRINT;
5195         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5196                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5197
5198         /* Add the domain admins group if we are a DC */
5199
5200         if ( IS_DC ) {
5201                 struct dom_sid domadmins_sid;
5202
5203                 sid_compose(&domadmins_sid, get_global_sam_sid(),
5204                             DOMAIN_RID_ADMINS);
5205
5206                 sa = PRINTER_ACE_FULL_CONTROL;
5207                 init_sec_ace(&ace[i++], &domadmins_sid,
5208                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5209                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5210                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5211                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5212         }
5213         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5214                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5215
5216                 sa = PRINTER_ACE_FULL_CONTROL;
5217                 init_sec_ace(&ace[i++], &adm_sid,
5218                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5219                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5220                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5221                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5222         }
5223
5224         /* add BUILTIN\Administrators as FULL CONTROL */
5225
5226         sa = PRINTER_ACE_FULL_CONTROL;
5227         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5228                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5229                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5230         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5231                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5232                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5233
5234         /* add BUILTIN\Print Operators as FULL CONTROL */
5235
5236         sa = PRINTER_ACE_FULL_CONTROL;
5237         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5238                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5239                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5240         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5241                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5242                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5243
5244         /* Make the security descriptor owned by the BUILTIN\Administrators */
5245
5246         /* The ACL revision number in rpc_secdesc.h differs from the one
5247            created by NT when setting ACE entries in printer
5248            descriptors.  NT4 complains about the property being edited by a
5249            NT5 machine. */
5250
5251         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5252                 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5253                         &global_sid_Builtin_Administrators,
5254                         &global_sid_Builtin_Administrators,
5255                         NULL, psa, &sd_size);
5256         }
5257
5258         if (!psd) {
5259                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5260                 return NULL;
5261         }
5262
5263         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5264
5265         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5266                  (unsigned int)sd_size));
5267
5268         return sdb;
5269 }
5270
5271 /****************************************************************************
5272  Get a security desc for a printer.
5273 ****************************************************************************/
5274
5275 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5276 {
5277         TDB_DATA kbuf;
5278         TDB_DATA dbuf;
5279         DATA_BLOB blob;
5280         char *temp;
5281         NTSTATUS status;
5282
5283         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5284                 sharename = temp + 1;
5285         }
5286
5287         /* Fetch security descriptor from tdb */
5288
5289         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5290
5291         dbuf = tdb_fetch(tdb_printers, kbuf);
5292         if (dbuf.dptr) {
5293
5294                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5295                                                  secdesc_ctr);
5296                 SAFE_FREE(dbuf.dptr);
5297
5298                 if (NT_STATUS_IS_OK(status)) {
5299                         return true;
5300                 }
5301         }
5302
5303         *secdesc_ctr = construct_default_printer_sdb(ctx);
5304         if (!*secdesc_ctr) {
5305                 return false;
5306         }
5307
5308         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5309                                        &blob.data, &blob.length);
5310         if (NT_STATUS_IS_OK(status)) {
5311                 dbuf.dptr = (unsigned char *)blob.data;
5312                 dbuf.dsize = blob.length;
5313                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5314                 talloc_free(blob.data);
5315         }
5316
5317         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5318            this security descriptor has been created when winbindd was
5319            down.  Take ownership of security descriptor. */
5320
5321         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5322                 struct dom_sid owner_sid;
5323
5324                 /* Change sd owner to workgroup administrator */
5325
5326                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5327                         struct sec_desc_buf *new_secdesc_ctr = NULL;
5328                         struct security_descriptor *psd = NULL;
5329                         size_t size;
5330
5331                         /* Create new sd */
5332
5333                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5334
5335                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5336                                             &owner_sid,
5337                                             (*secdesc_ctr)->sd->group_sid,
5338                                             (*secdesc_ctr)->sd->sacl,
5339                                             (*secdesc_ctr)->sd->dacl,
5340                                             &size);
5341
5342                         if (!psd) {
5343                                 return False;
5344                         }
5345
5346                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5347                         if (!new_secdesc_ctr) {
5348                                 return False;
5349                         }
5350
5351                         /* Swap with other one */
5352
5353                         *secdesc_ctr = new_secdesc_ctr;
5354
5355                         /* Set it */
5356
5357                         nt_printing_setsec(sharename, *secdesc_ctr);
5358                 }
5359         }
5360
5361         if (DEBUGLEVEL >= 10) {
5362                 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5363                 int i;
5364
5365                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5366                            sharename, the_acl->num_aces));
5367
5368                 for (i = 0; i < the_acl->num_aces; i++) {
5369                         DEBUG(10, ("%s %d %d 0x%08x\n",
5370                                    sid_string_dbg(&the_acl->aces[i].trustee),
5371                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5372                                    the_acl->aces[i].access_mask));
5373                 }
5374         }
5375
5376         return True;
5377 }
5378
5379 /* error code:
5380         0: everything OK
5381         1: level not implemented
5382         2: file doesn't exist
5383         3: can't allocate memory
5384         4: can't free memory
5385         5: non existant struct
5386 */
5387
5388 /*
5389         A printer and a printer driver are 2 different things.
5390         NT manages them separatelly, Samba does the same.
5391         Why ? Simply because it's easier and it makes sense !
5392
5393         Now explanation: You have 3 printers behind your samba server,
5394         2 of them are the same make and model (laser A and B). But laser B
5395         has an 3000 sheet feeder and laser A doesn't such an option.
5396         Your third printer is an old dot-matrix model for the accounting :-).
5397
5398         If the /usr/local/samba/lib directory (default dir), you will have
5399         5 files to describe all of this.
5400
5401         3 files for the printers (1 by printer):
5402                 NTprinter_laser A
5403                 NTprinter_laser B
5404                 NTprinter_accounting
5405         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5406                 NTdriver_printer model X
5407                 NTdriver_printer model Y
5408
5409 jfm: I should use this comment for the text file to explain
5410         same thing for the forms BTW.
5411         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5412
5413 */
5414
5415 /* Convert generic access rights to printer object specific access rights.
5416    It turns out that NT4 security descriptors use generic access rights and
5417    NT5 the object specific ones. */
5418
5419 void map_printer_permissions(struct security_descriptor *sd)
5420 {
5421         int i;
5422
5423         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5424                 se_map_generic(&sd->dacl->aces[i].access_mask,
5425                                &printer_generic_mapping);
5426         }
5427 }
5428
5429 void map_job_permissions(struct security_descriptor *sd)
5430 {
5431         int i;
5432
5433         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5434                 se_map_generic(&sd->dacl->aces[i].access_mask,
5435                                &job_generic_mapping);
5436         }
5437 }
5438
5439
5440 /****************************************************************************
5441  Check a user has permissions to perform the given operation.  We use the
5442  permission constants defined in include/rpc_spoolss.h to check the various
5443  actions we perform when checking printer access.
5444
5445    PRINTER_ACCESS_ADMINISTER:
5446        print_queue_pause, print_queue_resume, update_printer_sec,
5447        update_printer, spoolss_addprinterex_level_2,
5448        _spoolss_setprinterdata
5449
5450    PRINTER_ACCESS_USE:
5451        print_job_start
5452
5453    JOB_ACCESS_ADMINISTER:
5454        print_job_delete, print_job_pause, print_job_resume,
5455        print_queue_purge
5456
5457   Try access control in the following order (for performance reasons):
5458     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
5459     2)  check security descriptor (bit comparisons in memory)
5460     3)  "printer admins" (may result in numerous calls to winbind)
5461
5462  ****************************************************************************/
5463 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5464                         int access_type)
5465 {
5466         struct sec_desc_buf *secdesc = NULL;
5467         uint32 access_granted;
5468         NTSTATUS status;
5469         const char *pname;
5470         TALLOC_CTX *mem_ctx = NULL;
5471         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5472
5473         /* If user is NULL then use the current_user structure */
5474
5475         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5476
5477         if (server_info->utok.uid == sec_initial_uid()
5478             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5479                 return True;
5480         }
5481
5482         /* Get printer name */
5483
5484         pname = lp_printername(snum);
5485
5486         if (!pname || !*pname) {
5487                 errno = EACCES;
5488                 return False;
5489         }
5490
5491         /* Get printer security descriptor */
5492
5493         if(!(mem_ctx = talloc_init("print_access_check"))) {
5494                 errno = ENOMEM;
5495                 return False;
5496         }
5497
5498         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5499                 talloc_destroy(mem_ctx);
5500                 errno = ENOMEM;
5501                 return False;
5502         }
5503
5504         if (access_type == JOB_ACCESS_ADMINISTER) {
5505                 struct sec_desc_buf *parent_secdesc = secdesc;
5506
5507                 /* Create a child security descriptor to check permissions
5508                    against.  This is because print jobs are child objects
5509                    objects of a printer. */
5510
5511                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5512
5513                 if (!NT_STATUS_IS_OK(status)) {
5514                         talloc_destroy(mem_ctx);
5515                         errno = map_errno_from_nt_status(status);
5516                         return False;
5517                 }
5518
5519                 map_job_permissions(secdesc->sd);
5520         } else {
5521                 map_printer_permissions(secdesc->sd);
5522         }
5523
5524         /* Check access */
5525         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5526                                  &access_granted);
5527
5528         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5529
5530         /* see if we need to try the printer admin list */
5531
5532         if (!NT_STATUS_IS_OK(status) &&
5533             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5534                                          server_info->info3->base.domain.string,
5535                                          NULL, server_info->ptok,
5536                                          lp_printer_admin(snum)))) {
5537                 talloc_destroy(mem_ctx);
5538                 return True;
5539         }
5540
5541         talloc_destroy(mem_ctx);
5542
5543         if (!NT_STATUS_IS_OK(status)) {
5544                 errno = EACCES;
5545         }
5546
5547         return NT_STATUS_IS_OK(status);
5548 }
5549
5550 /****************************************************************************
5551  Check the time parameters allow a print operation.
5552 *****************************************************************************/
5553
5554 bool print_time_access_check(const char *servicename)
5555 {
5556         NT_PRINTER_INFO_LEVEL *printer = NULL;
5557         bool ok = False;
5558         time_t now = time(NULL);
5559         struct tm *t;
5560         uint32 mins;
5561
5562         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5563                 return False;
5564
5565         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5566                 ok = True;
5567
5568         t = gmtime(&now);
5569         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5570
5571         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5572                 ok = True;
5573
5574         free_a_printer(&printer, 2);
5575
5576         if (!ok)
5577                 errno = EACCES;
5578
5579         return ok;
5580 }
5581
5582 /****************************************************************************
5583  Fill in the servername sent in the _spoolss_open_printer_ex() call
5584 ****************************************************************************/
5585
5586 char* get_server_name( Printer_entry *printer )
5587 {
5588         return printer->servername;
5589 }
5590
5591