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