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