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