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