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