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