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