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