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