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