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