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