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