Fix from Martin Zielinski <mz@seh.de>. Don't delete files when
[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
3977 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3978                                 const char *servername,
3979                                 const char* sharename,
3980                                 bool get_loc_com)
3981 {
3982         int snum = lp_servicenumber(sharename);
3983
3984         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3985         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", 
3986                 servername, sharename);
3987         fstrcpy(info->sharename, sharename);
3988         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3989
3990         /* by setting the driver name to an empty string, a local NT admin
3991            can now run the **local** APW to install a local printer driver
3992            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3993            installed on the Samba server for NT clients --jerry */
3994 #if 0   /* JERRY --do not uncomment-- */
3995         if (!*info->drivername)
3996                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3997 #endif
3998
3999
4000         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4001
4002         strlcpy(info->comment, "", sizeof(info->comment));
4003         fstrcpy(info->printprocessor, "winprint");
4004         fstrcpy(info->datatype, "RAW");
4005
4006 #ifdef HAVE_CUPS
4007         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {             
4008                 /* Pull the location and comment strings from cups if we don't
4009                    already have one */
4010                 if ( !strlen(info->location) || !strlen(info->comment) )
4011                         cups_pull_comment_location( info );
4012         }
4013 #endif
4014
4015         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4016
4017         info->starttime = 0; /* Minutes since 12:00am GMT */
4018         info->untiltime = 0; /* Minutes since 12:00am GMT */
4019         info->priority = 1;
4020         info->default_priority = 1;
4021         info->setuptime = (uint32)time(NULL);
4022
4023         /*
4024          * I changed this as I think it is better to have a generic
4025          * DEVMODE than to crash Win2k explorer.exe   --jerry
4026          * See the HP Deskjet 990c Win2k drivers for an example.
4027          *
4028          * However the default devmode appears to cause problems
4029          * with the HP CLJ 8500 PCL driver.  Hence the addition of
4030          * the "default devmode" parameter   --jerry 22/01/2002
4031          */
4032
4033         if (lp_default_devmode(snum)) {
4034                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4035                         goto fail;
4036                 }
4037         } else {
4038                 info->devmode = NULL;
4039         }
4040
4041         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4042                 goto fail;
4043         }
4044
4045         return WERR_OK;
4046
4047 fail:
4048         if (info->devmode)
4049                 free_nt_devicemode(&info->devmode);
4050
4051         return WERR_ACCESS_DENIED;
4052 }
4053
4054 /****************************************************************************
4055 ****************************************************************************/
4056
4057 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4058                                 const char *servername,
4059                                 const char *sharename,
4060                                 bool get_loc_com)
4061 {
4062         int len = 0;
4063         int snum = lp_servicenumber(sharename);
4064         TDB_DATA kbuf, dbuf;
4065         fstring printername;
4066         char adevice[MAXDEVICENAME];
4067         char *comment = NULL;
4068
4069         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4070
4071         dbuf = tdb_fetch(tdb_printers, kbuf);
4072         if (!dbuf.dptr) {
4073                 return get_a_printer_2_default(info, servername,
4074                                         sharename, get_loc_com);
4075         }
4076
4077         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4078                         &info->attributes,
4079                         &info->priority,
4080                         &info->default_priority,
4081                         &info->starttime,
4082                         &info->untiltime,
4083                         &info->status,
4084                         &info->cjobs,
4085                         &info->averageppm,
4086                         &info->changeid,
4087                         &info->c_setprinter,
4088                         &info->setuptime,
4089                         info->servername,
4090                         info->printername,
4091                         info->sharename,
4092                         info->portname,
4093                         info->drivername,
4094                         &comment,
4095                         info->location,
4096                         info->sepfile,
4097                         info->printprocessor,
4098                         info->datatype,
4099                         info->parameters);
4100
4101         if (comment) {
4102                 strlcpy(info->comment, comment, sizeof(info->comment));
4103                 SAFE_FREE(comment);
4104         }
4105
4106         /* Samba has to have shared raw drivers. */
4107         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4108         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4109
4110         /* Restore the stripped strings. */
4111         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4112
4113         if ( lp_force_printername(snum) ) {
4114                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4115         } else {
4116                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4117         }
4118
4119         fstrcpy(info->printername, printername);
4120
4121 #ifdef HAVE_CUPS
4122         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4123                 /* Pull the location and comment strings from cups if we don't
4124                    already have one */
4125                 if ( !strlen(info->location) || !strlen(info->comment) )
4126                         cups_pull_comment_location( info );
4127         }
4128 #endif
4129
4130         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4131
4132         /*
4133          * Some client drivers freak out if there is a NULL devmode
4134          * (probably the driver is not checking before accessing 
4135          * the devmode pointer)   --jerry
4136          *
4137          * See comments in get_a_printer_2_default()
4138          */
4139
4140         if (lp_default_devmode(snum) && !info->devmode) {
4141                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4142                         printername));
4143                 info->devmode = construct_nt_devicemode(printername);
4144         }
4145
4146         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4147         if (info->devmode) {
4148                 fstrcpy(info->devmode->devicename, adevice);    
4149         }
4150
4151         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4152                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4153                 SAFE_FREE(dbuf.dptr);
4154                 return WERR_NOMEM;
4155         }
4156         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4157
4158         /* This will get the current RPC talloc context, but we should be
4159            passing this as a parameter... fixme... JRA ! */
4160
4161         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4162                 SAFE_FREE(dbuf.dptr);
4163                 return WERR_NOMEM;
4164         }
4165
4166         /* Fix for OS/2 drivers. */
4167
4168         if (get_remote_arch() == RA_OS2) {
4169                 map_to_os2_driver(info->drivername);
4170         }
4171
4172         SAFE_FREE(dbuf.dptr);
4173
4174         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4175                  sharename, info->printername, info->drivername));
4176
4177         return WERR_OK; 
4178 }
4179
4180 /****************************************************************************
4181  Debugging function, dump at level 6 the struct in the logs.
4182 ****************************************************************************/
4183 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4184 {
4185         uint32 result;
4186         NT_PRINTER_INFO_LEVEL_2 *info2;
4187         
4188         DEBUG(106,("Dumping printer at level [%d]\n", level));
4189         
4190         switch (level) {
4191                 case 2:
4192                 {
4193                         if (printer->info_2 == NULL)
4194                                 result=5;
4195                         else
4196                         {
4197                                 info2=printer->info_2;
4198                         
4199                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4200                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4201                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4202                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4203                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4204                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4205                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4206                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4207                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4208                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4209                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4210
4211                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4212                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4213                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4214                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4215                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4216                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4217                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4218                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4219                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4220                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4221                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4222                                 result=0;
4223                         }
4224                         break;
4225                 }
4226                 default:
4227                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4228                         result=1;
4229                         break;
4230         }
4231         
4232         return result;
4233 }
4234
4235 /****************************************************************************
4236  Update the changeid time.
4237  This is SO NASTY as some drivers need this to change, others need it
4238  static. This value will change every second, and I must hope that this
4239  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4240  UTAH ! JRA.
4241 ****************************************************************************/
4242
4243 static uint32 rev_changeid(void)
4244 {
4245         struct timeval tv;
4246
4247         get_process_uptime(&tv);
4248
4249 #if 1   /* JERRY */
4250         /* Return changeid as msec since spooler restart */
4251         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4252 #else
4253         /*
4254          * This setting seems to work well but is too untested
4255          * to replace the above calculation.  Left in for experiementation
4256          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4257          */
4258         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4259 #endif
4260 }
4261
4262
4263 /*
4264  * The function below are the high level ones.
4265  * only those ones must be called from the spoolss code.
4266  * JFM.
4267  */
4268
4269 /****************************************************************************
4270  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4271 ****************************************************************************/
4272
4273 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4274 {
4275         WERROR result;
4276         
4277         dump_a_printer(printer, level); 
4278         
4279         switch (level) {
4280                 case 2:
4281                 {
4282                         /*
4283                          * Update the changestamp.  Emperical tests show that the
4284                          * ChangeID is always updated,but c_setprinter is  
4285                          *  global spooler variable (not per printer).
4286                          */
4287
4288                         /* ChangeID **must** be increasing over the lifetime
4289                            of client's spoolss service in order for the
4290                            client's cache to show updates */
4291
4292                         printer->info_2->changeid = rev_changeid();
4293
4294                         /*
4295                          * Because one day someone will ask:
4296                          * NT->NT       An admin connection to a remote
4297                          *              printer show changes imeediately in
4298                          *              the properities dialog
4299                          *      
4300                          *              A non-admin connection will only show the
4301                          *              changes after viewing the properites page
4302                          *              2 times.  Seems to be related to a
4303                          *              race condition in the client between the spooler
4304                          *              updating the local cache and the Explorer.exe GUI
4305                          *              actually displaying the properties.
4306                          *
4307                          *              This is fixed in Win2k.  admin/non-admin
4308                          *              connections both display changes immediately.
4309                          *
4310                          * 14/12/01     --jerry
4311                          */
4312
4313                         result=update_a_printer_2(printer->info_2);
4314                         break;
4315                 }
4316                 default:
4317                         result=WERR_UNKNOWN_LEVEL;
4318                         break;
4319         }
4320
4321         return result;
4322 }
4323
4324 /****************************************************************************
4325  Initialize printer devmode & data with previously saved driver init values.
4326 ****************************************************************************/
4327
4328 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4329 {
4330         int                     len = 0;
4331         char *key = NULL;
4332         TDB_DATA                dbuf;
4333         NT_PRINTER_INFO_LEVEL_2 info;
4334
4335
4336         ZERO_STRUCT(info);
4337
4338         /*
4339          * Delete any printer data 'values' already set. When called for driver
4340          * replace, there will generally be some, but during an add printer, there
4341          * should not be any (if there are delete them).
4342          */
4343
4344         if ( info_ptr->data )
4345                 delete_all_printer_data( info_ptr, "" );
4346
4347         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4348                                 info_ptr->drivername) < 0) {
4349                 return false;
4350         }
4351
4352         dbuf = tdb_fetch_bystring(tdb_drivers, key);
4353         if (!dbuf.dptr) {
4354                 /*
4355                  * When changing to a driver that has no init info in the tdb, remove
4356                  * the previous drivers init info and leave the new on blank.
4357                  */
4358                 free_nt_devicemode(&info_ptr->devmode);
4359                 SAFE_FREE(key);
4360                 return false;
4361         }
4362
4363         SAFE_FREE(key);
4364         /*
4365          * Get the saved DEVMODE..
4366          */
4367
4368         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4369
4370         /*
4371          * The saved DEVMODE contains the devicename from the printer used during
4372          * the initialization save. Change it to reflect the new printer.
4373          */
4374
4375         if ( info.devmode ) {
4376                 ZERO_STRUCT(info.devmode->devicename);
4377                 fstrcpy(info.devmode->devicename, info_ptr->printername);
4378         }
4379
4380         /*
4381          * NT/2k does not change out the entire DeviceMode of a printer
4382          * when changing the driver.  Only the driverextra, private, &
4383          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
4384          *
4385          * Later examination revealed that Windows NT/2k does reset the
4386          * the printer's device mode, bit **only** when you change a
4387          * property of the device mode such as the page orientation.
4388          * --jerry
4389          */
4390
4391
4392         /* Bind the saved DEVMODE to the new the printer */
4393
4394         free_nt_devicemode(&info_ptr->devmode);
4395         info_ptr->devmode = info.devmode;
4396
4397         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4398                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4399
4400         /* Add the printer data 'values' to the new printer */
4401
4402         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4403                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4404                 return False;
4405         }
4406
4407         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4408
4409         SAFE_FREE(dbuf.dptr);
4410
4411         return true;
4412 }
4413
4414 /****************************************************************************
4415  Initialize printer devmode & data with previously saved driver init values.
4416  When a printer is created using AddPrinter, the drivername bound to the
4417  printer is used to lookup previously saved driver initialization info, which
4418  is bound to the new printer.
4419 ****************************************************************************/
4420
4421 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4422 {
4423         bool result = False;
4424
4425         switch (level) {
4426                 case 2:
4427                         result = set_driver_init_2(printer->info_2);
4428                         break;
4429
4430                 default:
4431                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4432                                 level));
4433                         break;
4434         }
4435
4436         return result;
4437 }
4438
4439 /****************************************************************************
4440  Delete driver init data stored for a specified driver
4441 ****************************************************************************/
4442
4443 bool del_driver_init(char *drivername)
4444 {
4445         char *key;
4446         bool ret;
4447
4448         if (!drivername || !*drivername) {
4449                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4450                 return false;
4451         }
4452
4453         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4454                 return false;
4455         }
4456
4457         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4458                                 drivername));
4459
4460         ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4461         SAFE_FREE(key);
4462         return ret;
4463 }
4464
4465 /****************************************************************************
4466  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
4467  in the tdb. Note: this is different from the driver entry and the printer
4468  entry. There should be a single driver init entry for each driver regardless
4469  of whether it was installed from NT or 2K. Technically, they should be
4470  different, but they work out to the same struct.
4471 ****************************************************************************/
4472
4473 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4474 {
4475         char *key = NULL;
4476         uint8 *buf;
4477         int buflen, len, ret;
4478         int retlen;
4479         TDB_DATA dbuf;
4480
4481         buf = NULL;
4482         buflen = 0;
4483
4484  again:
4485         len = 0;
4486         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4487
4488         retlen = pack_values( info->data, buf+len, buflen-len );
4489         if (retlen == -1) {
4490                 ret = -1;
4491                 goto done;
4492         }
4493         len += retlen;
4494
4495         if (buflen < len) {
4496                 buf = (uint8 *)SMB_REALLOC(buf, len);
4497                 if (!buf) {
4498                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4499                         ret = -1;
4500                         goto done;
4501                 }
4502                 buflen = len;
4503                 goto again;
4504         }
4505
4506         SAFE_FREE(key);
4507         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4508                 ret = (uint32)-1;
4509                 goto done;
4510         }
4511
4512         dbuf.dptr = buf;
4513         dbuf.dsize = len;
4514
4515         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4516
4517 done:
4518         if (ret == -1)
4519                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4520
4521         SAFE_FREE(buf);
4522
4523         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4524                  info->sharename, info->drivername));
4525
4526         return ret;
4527 }
4528
4529 /****************************************************************************
4530  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4531 ****************************************************************************/
4532
4533 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4534 {
4535         uint32 result;
4536         
4537         dump_a_printer(printer, level); 
4538         
4539         switch (level) {
4540                 case 2:
4541                         result = update_driver_init_2(printer->info_2);
4542                         break;
4543                 default:
4544                         result = 1;
4545                         break;
4546         }
4547         
4548         return result;
4549 }
4550
4551 /****************************************************************************
4552  Convert the printer data value, a REG_BINARY array, into an initialization 
4553  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4554  got to keep the endians happy :).
4555 ****************************************************************************/
4556
4557 static bool convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4558 {
4559         bool       result = False;
4560         prs_struct ps;
4561         DEVICEMODE devmode;
4562
4563         ZERO_STRUCT(devmode);
4564
4565         prs_init_empty(&ps, ctx, UNMARSHALL);
4566         ps.data_p      = (char *)data;
4567         ps.buffer_size = data_len;
4568
4569         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4570                 result = convert_devicemode("", &devmode, &nt_devmode);
4571         else
4572                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4573
4574         return result;
4575 }
4576
4577 /****************************************************************************
4578  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4579
4580  1. Use the driver's config DLL to this UNC printername and:
4581     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4582     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4583  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4584
4585  The last step triggers saving the "driver initialization" information for
4586  this printer into the tdb. Later, new printers that use this driver will
4587  have this initialization information bound to them. This simulates the
4588  driver initialization, as if it had run on the Samba server (as it would
4589  have done on NT).
4590
4591  The Win32 client side code requirement sucks! But until we can run arbitrary
4592  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4593  
4594  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4595  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4596  about it and you will realize why.  JRR 010720
4597 ****************************************************************************/
4598
4599 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4600 {
4601         WERROR        status       = WERR_OK;
4602         TALLOC_CTX    *ctx         = NULL;
4603         NT_DEVICEMODE *nt_devmode  = NULL;
4604         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4605         
4606         /*
4607          * When the DEVMODE is already set on the printer, don't try to unpack it.
4608          */
4609         DEBUG(8,("save_driver_init_2: Enter...\n"));
4610         
4611         if ( !printer->info_2->devmode && data_len ) {
4612                 /*
4613                  * Set devmode on printer info, so entire printer initialization can be
4614                  * saved to tdb.
4615                  */
4616
4617                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4618                         return WERR_NOMEM;
4619
4620                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4621                         status = WERR_NOMEM;
4622                         goto done;
4623                 }
4624         
4625                 ZERO_STRUCTP(nt_devmode);
4626
4627                 /*
4628                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4629                  * Convert it to to a devmode structure
4630                  */
4631                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4632                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4633                         status = WERR_INVALID_PARAM;
4634                         goto done;
4635                 }
4636
4637                 printer->info_2->devmode = nt_devmode;
4638         }
4639
4640         /*
4641          * Pack up and add (or update) the DEVMODE and any current printer data to
4642          * a 'driver init' element in the tdb
4643          * 
4644          */
4645
4646         if ( update_driver_init(printer, 2) != 0 ) {
4647                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4648                 status = WERR_NOMEM;
4649                 goto done;
4650         }
4651         
4652         /*
4653          * If driver initialization info was successfully saved, set the current 
4654          * printer to match it. This allows initialization of the current printer 
4655          * as well as the driver.
4656          */
4657         status = mod_a_printer(printer, 2);
4658         if (!W_ERROR_IS_OK(status)) {
4659                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4660                                   printer->info_2->printername));
4661         }
4662         
4663   done:
4664         talloc_destroy(ctx);
4665         free_nt_devicemode( &nt_devmode );
4666         
4667         printer->info_2->devmode = tmp_devmode;
4668
4669         return status;
4670 }
4671
4672 /****************************************************************************
4673  Update the driver init info (DEVMODE and specifics) for a printer
4674 ****************************************************************************/
4675
4676 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4677 {
4678         WERROR status = WERR_OK;
4679         
4680         switch (level) {
4681                 case 2:
4682                         status = save_driver_init_2( printer, data, data_len );
4683                         break;
4684                 default:
4685                         status = WERR_UNKNOWN_LEVEL;
4686                         break;
4687         }
4688         
4689         return status;
4690 }
4691
4692 /****************************************************************************
4693  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4694
4695  Previously the code had a memory allocation problem because it always
4696  used the TALLOC_CTX from the Printer_entry*.   This context lasts 
4697  as a long as the original handle is open.  So if the client made a lot 
4698  of getprinter[data]() calls, the memory usage would climb.  Now we use
4699  a short lived TALLOC_CTX for printer_info_2 objects returned.  We 
4700  still use the Printer_entry->ctx for maintaining the cache copy though
4701  since that object must live as long as the handle by definition.  
4702                                                     --jerry
4703
4704 ****************************************************************************/
4705
4706 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
4707                         const char *sharename, bool get_loc_com)
4708 {
4709         WERROR result;
4710         fstring servername;
4711         
4712         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4713
4714         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4715                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4716                 return WERR_NOMEM;
4717         }
4718
4719         switch (level) {
4720                 case 2:
4721                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4722                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4723                                 TALLOC_FREE( *pp_printer );
4724                                 return WERR_NOMEM;
4725                         }
4726
4727                         if ( print_hnd ) 
4728                                 fstrcpy( servername, print_hnd->servername );
4729                         else {
4730                                 fstrcpy( servername, "%L" );
4731                                 standard_sub_basic( "", "", servername,
4732                                                     sizeof(servername)-1 );
4733                         }
4734
4735                         result = get_a_printer_2( (*pp_printer)->info_2,
4736                                         servername, sharename, get_loc_com);
4737
4738                         /* we have a new printer now.  Save it with this handle */
4739
4740                         if ( !W_ERROR_IS_OK(result) ) {
4741                                 TALLOC_FREE( *pp_printer );
4742                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 
4743                                         sharename, (unsigned int)level, dos_errstr(result)));
4744                                 return result;
4745                         }
4746
4747                         dump_a_printer( *pp_printer, level);
4748                         
4749                         break;
4750                         
4751                 default:
4752                         TALLOC_FREE( *pp_printer );
4753                         return WERR_UNKNOWN_LEVEL;
4754         }
4755         
4756         return WERR_OK;
4757 }
4758
4759 WERROR get_a_printer( Printer_entry *print_hnd,
4760                         NT_PRINTER_INFO_LEVEL **pp_printer,
4761                         uint32 level,
4762                         const char *sharename)
4763 {
4764         return get_a_printer_internal(print_hnd, pp_printer, level,
4765                                         sharename, true);
4766 }
4767
4768 WERROR get_a_printer_search( Printer_entry *print_hnd,
4769                         NT_PRINTER_INFO_LEVEL **pp_printer,
4770                         uint32 level,
4771                         const char *sharename)
4772 {
4773         return get_a_printer_internal(print_hnd, pp_printer, level,
4774                                         sharename, false);
4775 }
4776
4777 /****************************************************************************
4778  Deletes a NT_PRINTER_INFO_LEVEL struct.
4779 ****************************************************************************/
4780
4781 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4782 {
4783         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4784
4785         if ( !printer )
4786                 return 0;
4787         
4788         switch (level) {
4789                 case 2:
4790                         if ( printer->info_2 ) 
4791                                 free_nt_printer_info_level_2(&printer->info_2);
4792                         break;
4793
4794                 default:
4795                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4796                         return 1;
4797         }
4798
4799         TALLOC_FREE(*pp_printer);
4800
4801         return 0;
4802 }
4803
4804 /****************************************************************************
4805 ****************************************************************************/
4806 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4807 {
4808         uint32 result;
4809         DEBUG(104,("adding a printer at level [%d]\n", level));
4810         dump_a_printer_driver(driver, level);
4811         
4812         switch (level) {
4813                 case 3:
4814                         result=add_a_printer_driver_3(driver.info_3);
4815                         break;
4816
4817                 case 6:
4818                         result=add_a_printer_driver_6(driver.info_6);
4819                         break;
4820
4821                 default:
4822                         result=1;
4823                         break;
4824         }
4825         
4826         return result;
4827 }
4828 /****************************************************************************
4829 ****************************************************************************/
4830
4831 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4832                             fstring drivername, const char *architecture, uint32 version)
4833 {
4834         WERROR result;
4835         
4836         switch (level) {
4837                 case 3:
4838                         /* Sometime we just want any version of the driver */
4839                         
4840                         if ( version == DRIVER_ANY_VERSION ) {
4841                                 /* look for Win2k first and then for NT4 */
4842                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4843                                                 architecture, 3);
4844                                                 
4845                                 if ( !W_ERROR_IS_OK(result) ) {
4846                                         result = get_a_printer_driver_3( &driver->info_3, 
4847                                                         drivername, architecture, 2 );
4848                                 }
4849                         } else {
4850                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4851                                         architecture, version);                         
4852                         }
4853                         break;
4854                         
4855                 default:
4856                         result=W_ERROR(1);
4857                         break;
4858         }
4859         
4860         if (W_ERROR_IS_OK(result))
4861                 dump_a_printer_driver(*driver, level);
4862                 
4863         return result;
4864 }
4865
4866 /****************************************************************************
4867 ****************************************************************************/
4868 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4869 {
4870         uint32 result;
4871         
4872         switch (level) {
4873                 case 3:
4874                 {
4875                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4876                         if (driver.info_3 != NULL)
4877                         {
4878                                 info3=driver.info_3;
4879                                 SAFE_FREE(info3->dependentfiles);
4880                                 ZERO_STRUCTP(info3);
4881                                 SAFE_FREE(info3);
4882                                 result=0;
4883                         } else {
4884                                 result=4;
4885                         }
4886                         break;
4887                 }
4888                 case 6:
4889                 {
4890                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4891                         if (driver.info_6 != NULL) {
4892                                 info6=driver.info_6;
4893                                 SAFE_FREE(info6->dependentfiles);
4894                                 SAFE_FREE(info6->previousnames);
4895                                 ZERO_STRUCTP(info6);
4896                                 SAFE_FREE(info6);
4897                                 result=0;
4898                         } else {
4899                                 result=4;
4900                         }
4901                         break;
4902                 }
4903                 default:
4904                         result=1;
4905                         break;
4906         }
4907         return result;
4908 }
4909
4910
4911 /****************************************************************************
4912   Determine whether or not a particular driver is currently assigned
4913   to a printer
4914 ****************************************************************************/
4915
4916 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4917 {
4918         int snum;
4919         int n_services = lp_numservices();
4920         NT_PRINTER_INFO_LEVEL *printer = NULL;
4921         bool in_use = False;
4922
4923         if ( !info_3 ) 
4924                 return False;
4925
4926         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4927         
4928         /* loop through the printers.tdb and check for the drivername */
4929         
4930         for (snum=0; snum<n_services && !in_use; snum++) {
4931                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4932                         continue;
4933                 
4934                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4935                         continue;
4936                 
4937                 if ( strequal(info_3->name, printer->info_2->drivername) ) 
4938                         in_use = True;
4939                 
4940                 free_a_printer( &printer, 2 );
4941         }
4942         
4943         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4944         
4945         if ( in_use ) {
4946                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4947                 WERROR werr;
4948                 
4949                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4950                 
4951                 /* we can still remove the driver if there is one of 
4952                    "Windows NT x86" version 2 or 3 left */
4953                    
4954                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4955                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );                       
4956                 }
4957                 else {
4958                         switch ( info_3->cversion ) {
4959                         case 2:
4960                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4961                                 break;
4962                         case 3: 
4963                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4964                                 break;
4965                         default:
4966                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 
4967                                         info_3->cversion));
4968                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4969                                 break;
4970                         }
4971                 }
4972
4973                 /* now check the error code */
4974                                 
4975                 if ( W_ERROR_IS_OK(werr) ) {
4976                         /* it's ok to remove the driver, we have other architctures left */
4977                         in_use = False;
4978                         free_a_printer_driver( d, 3 );
4979                 }
4980         }
4981         
4982         /* report that the driver is not in use by default */
4983         
4984         return in_use;
4985 }
4986
4987
4988 /**********************************************************************
4989  Check to see if a ogiven file is in use by *info
4990  *********************************************************************/
4991  
4992 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4993 {
4994         int i = 0;
4995
4996         if ( !info )
4997                 return False;
4998
4999         /* mz: skip files that are in the list but already deleted */
5000         if (!file || !file[0]) {
5001                 return false;
5002         }
5003
5004         if ( strequal(file, info->driverpath) )
5005                 return True;
5006
5007         if ( strequal(file, info->datafile) )
5008                 return True;
5009
5010         if ( strequal(file, info->configfile) )
5011                 return True;
5012
5013         if ( strequal(file, info->helpfile) )
5014                 return True;
5015         
5016         /* see of there are any dependent files to examine */
5017         
5018         if ( !info->dependentfiles )
5019                 return False;
5020         
5021         while ( *info->dependentfiles[i] ) {
5022                 if ( strequal(file, info->dependentfiles[i]) )
5023                         return True;
5024                 i++;
5025         }
5026         
5027         return False;
5028
5029 }
5030
5031 /**********************************************************************
5032  Utility function to remove the dependent file pointed to by the 
5033  input parameter from the list 
5034  *********************************************************************/
5035
5036 static void trim_dependent_file( fstring files[], int idx )
5037 {
5038         
5039         /* bump everything down a slot */
5040
5041         while( *files[idx+1] ) {
5042                 fstrcpy( files[idx], files[idx+1] );
5043                 idx++;
5044         }
5045         
5046         *files[idx] = '\0';
5047
5048         return; 
5049 }
5050
5051 /**********************************************************************
5052  Check if any of the files used by src are also used by drv 
5053  *********************************************************************/
5054
5055 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
5056                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
5057 {
5058         bool    in_use = False;
5059         int     i = 0;
5060         
5061         if ( !src || !drv )
5062                 return False;
5063                 
5064         /* check each file.  Remove it from the src structure if it overlaps */
5065         
5066         if ( drv_file_in_use(src->driverpath, drv) ) {
5067                 in_use = True;
5068                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
5069                 fstrcpy( src->driverpath, "" );
5070         }
5071                 
5072         if ( drv_file_in_use(src->datafile, drv) ) {
5073                 in_use = True;
5074                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
5075                 fstrcpy( src->datafile, "" );
5076         }
5077                 
5078         if ( drv_file_in_use(src->configfile, drv) ) {
5079                 in_use = True;
5080                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5081                 fstrcpy( src->configfile, "" );
5082         }
5083                 
5084         if ( drv_file_in_use(src->helpfile, drv) ) {
5085                 in_use = True;
5086                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5087                 fstrcpy( src->helpfile, "" );
5088         }
5089         
5090         /* are there any dependentfiles to examine? */
5091         
5092         if ( !src->dependentfiles )
5093                 return in_use;
5094                 
5095         while ( *src->dependentfiles[i] ) {
5096                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5097                         in_use = True;
5098                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5099                         trim_dependent_file( src->dependentfiles, i );
5100                 } else
5101                         i++;
5102         }               
5103                 
5104         return in_use;
5105 }
5106
5107 /****************************************************************************
5108   Determine whether or not a particular driver files are currently being 
5109   used by any other driver.  
5110   
5111   Return value is True if any files were in use by other drivers
5112   and False otherwise.
5113   
5114   Upon return, *info has been modified to only contain the driver files
5115   which are not in use
5116
5117   Fix from mz:
5118
5119   This needs to check all drivers to ensure that all files in use
5120   have been removed from *info, not just the ones in the first
5121   match.
5122 ****************************************************************************/
5123
5124 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5125 {
5126         int                             i;
5127         int                             ndrivers;
5128         uint32                          version;
5129         fstring                         *list = NULL;
5130         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5131         bool in_use = false;
5132
5133         if ( !info )
5134                 return False;
5135         
5136         version = info->cversion;
5137         
5138         /* loop over all driver versions */
5139         
5140         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5141         
5142         /* get the list of drivers */
5143                 
5144         list = NULL;
5145         ndrivers = get_ntdrivers(&list, info->environment, version);
5146                 
5147         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
5148                 ndrivers, info->environment, version));
5149
5150         /* check each driver for overlap in files */
5151                 
5152         for (i=0; i<ndrivers; i++) {
5153                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5154                         
5155                 ZERO_STRUCT(driver);
5156                         
5157                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5158                         SAFE_FREE(list);
5159                         return True;
5160                 }
5161                         
5162                 /* check if d2 uses any files from d1 */
5163                 /* only if this is a different driver than the one being deleted */
5164                         
5165                 if ( !strequal(info->name, driver.info_3->name) ) {
5166                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
5167                                 /* mz: Do not instantly return -
5168                                  * we need to ensure this file isn't
5169                                  * also in use by other drivers. */
5170                                 in_use = true;
5171                         }
5172                 }
5173
5174                 free_a_printer_driver(driver, 3);
5175         }
5176
5177         SAFE_FREE(list);
5178
5179         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5180
5181         driver.info_3 = info;
5182
5183         if ( DEBUGLEVEL >= 20 )
5184                 dump_a_printer_driver( driver, 3 );
5185
5186         return in_use;
5187 }
5188
5189 /****************************************************************************
5190   Actually delete the driver files.  Make sure that
5191   printer_driver_files_in_use() return False before calling
5192   this.
5193 ****************************************************************************/
5194
5195 static bool delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
5196 {
5197         int i = 0;
5198         char *s;
5199         const char *file;
5200         connection_struct *conn;
5201         DATA_BLOB null_pw;
5202         NTSTATUS nt_status;
5203         fstring res_type;
5204         SMB_STRUCT_STAT  st;
5205
5206         if ( !info_3 )
5207                 return False;
5208
5209         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5210
5211         /*
5212          * Connect to the print$ share under the same account as the
5213          * user connected to the rpc pipe. Note we must be root to
5214          * do this.
5215          */
5216
5217         null_pw = data_blob_null;
5218         fstrcpy(res_type, "A:");
5219         become_root();
5220         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
5221         unbecome_root();
5222
5223         if ( !conn ) {
5224                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
5225                 return False;
5226         }
5227
5228         if ( !CAN_WRITE(conn) ) {
5229                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5230                 return False;
5231         }
5232
5233         /* Save who we are - we are temporarily becoming the connection user. */
5234
5235         if ( !become_user(conn, conn->vuid) ) {
5236                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
5237                 return False;
5238         }
5239
5240         /* now delete the files; must strip the '\print$' string from
5241            fron of path                                                */
5242
5243         if ( *info_3->driverpath ) {
5244                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5245                         file = s;
5246                         driver_unix_convert(conn,file,&st);
5247                         DEBUG(10,("deleting driverfile [%s]\n", s));
5248                         unlink_internals(conn, NULL, 0, file, False);
5249                 }
5250         }
5251
5252         if ( *info_3->configfile ) {
5253                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5254                         file = s;
5255                         driver_unix_convert(conn,file,&st);
5256                         DEBUG(10,("deleting configfile [%s]\n", s));
5257                         unlink_internals(conn, NULL, 0, file, False);
5258                 }
5259         }
5260
5261         if ( *info_3->datafile ) {
5262                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5263                         file = s;
5264                         driver_unix_convert(conn,file,&st);
5265                         DEBUG(10,("deleting datafile [%s]\n", s));
5266                         unlink_internals(conn, NULL, 0, file, False);
5267                 }
5268         }
5269
5270         if ( *info_3->helpfile ) {
5271                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5272                         file = s;
5273                         driver_unix_convert(conn,file,&st);
5274                         DEBUG(10,("deleting helpfile [%s]\n", s));
5275                         unlink_internals(conn, NULL, 0, file, False);
5276                 }
5277         }
5278
5279         /* check if we are done removing files */
5280
5281         if ( info_3->dependentfiles ) {
5282                 while ( info_3->dependentfiles[i][0] ) {
5283                         char *p;
5284
5285                         /* bypass the "\print$" portion of the path */
5286
5287                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5288                                 file = p;
5289                                 driver_unix_convert(conn,file,&st);
5290                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5291                                 unlink_internals(conn, NULL, 0, file, False);
5292                         }
5293
5294                         i++;
5295                 }
5296         }
5297
5298         unbecome_user();
5299
5300         return true;
5301 }
5302
5303 /****************************************************************************
5304  Remove a printer driver from the TDB.  This assumes that the the driver was
5305  previously looked up.
5306  ***************************************************************************/
5307
5308 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5309                               uint32 version, bool delete_files )
5310 {
5311         char *key = NULL;
5312         const char     *arch;
5313         TDB_DATA        dbuf;
5314         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
5315
5316         /* delete the tdb data first */
5317
5318         arch = get_short_archi(info_3->environment);
5319         if (!arch) {
5320                 return WERR_UNKNOWN_PRINTER_DRIVER;
5321         }
5322         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5323                         arch, version, info_3->name) < 0) {
5324                 return WERR_NOMEM;
5325         }
5326
5327         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5328                 key, delete_files ? "TRUE" : "FALSE" ));
5329
5330         ctr.info_3 = info_3;
5331         dump_a_printer_driver( ctr, 3 );
5332
5333         /* check if the driver actually exists for this environment */
5334
5335         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5336         if ( !dbuf.dptr ) {
5337                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5338                 SAFE_FREE(key);
5339                 return WERR_UNKNOWN_PRINTER_DRIVER;
5340         }
5341
5342         SAFE_FREE( dbuf.dptr );
5343
5344         /* ok... the driver exists so the delete should return success */
5345
5346         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5347                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5348                 SAFE_FREE(key);
5349                 return WERR_ACCESS_DENIED;
5350         }
5351
5352         /*
5353          * now delete any associated files if delete_files == True
5354          * even if this part failes, we return succes because the
5355          * driver doesn not exist any more
5356          */
5357
5358         if ( delete_files )
5359                 delete_driver_files( info_3, user );
5360
5361         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5362         SAFE_FREE(key);
5363
5364         return WERR_OK;
5365 }
5366
5367 /****************************************************************************
5368  Store a security desc for a printer.
5369 ****************************************************************************/
5370
5371 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5372 {
5373         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5374         SEC_DESC_BUF *old_secdesc_ctr = NULL;
5375         prs_struct ps;
5376         bool prs_init_done = false;
5377         TALLOC_CTX *mem_ctx = NULL;
5378         TDB_DATA kbuf;
5379         WERROR status;
5380
5381         mem_ctx = talloc_init("nt_printing_setsec");
5382         if (mem_ctx == NULL)
5383                 return WERR_NOMEM;
5384
5385         /* The old owner and group sids of the security descriptor are not
5386            present when new ACEs are added or removed by changing printer
5387            permissions through NT.  If they are NULL in the new security
5388            descriptor then copy them over from the old one. */
5389
5390         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5391                 DOM_SID *owner_sid, *group_sid;
5392                 SEC_ACL *dacl, *sacl;
5393                 SEC_DESC *psd = NULL;
5394                 size_t size;
5395
5396                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5397                         status = WERR_NOMEM;
5398                         goto out;
5399                 }
5400
5401                 /* Pick out correct owner and group sids */
5402
5403                 owner_sid = secdesc_ctr->sd->owner_sid ?
5404                         secdesc_ctr->sd->owner_sid :
5405                         old_secdesc_ctr->sd->owner_sid;
5406
5407                 group_sid = secdesc_ctr->sd->group_sid ?
5408                         secdesc_ctr->sd->group_sid :
5409                         old_secdesc_ctr->sd->group_sid;
5410
5411                 dacl = secdesc_ctr->sd->dacl ?
5412                         secdesc_ctr->sd->dacl :
5413                         old_secdesc_ctr->sd->dacl;
5414
5415                 sacl = secdesc_ctr->sd->sacl ?
5416                         secdesc_ctr->sd->sacl :
5417                         old_secdesc_ctr->sd->sacl;
5418
5419                 /* Make a deep copy of the security descriptor */
5420
5421                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5422                                     owner_sid, group_sid,
5423                                     sacl,
5424                                     dacl,
5425                                     &size);
5426
5427                 if (!psd) {
5428                         status = WERR_NOMEM;
5429                         goto out;
5430                 }
5431
5432                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5433         }
5434
5435         if (!new_secdesc_ctr) {
5436                 new_secdesc_ctr = secdesc_ctr;
5437         }
5438
5439         /* Store the security descriptor in a tdb */
5440
5441         if (!prs_init(&ps,
5442                 (uint32)ndr_size_security_descriptor(new_secdesc_ctr->sd, 0)
5443                 + sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL) ) {
5444                 status = WERR_NOMEM;
5445                 goto out;
5446         }
5447
5448
5449         prs_init_done = true;
5450
5451         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5452                              &ps, 1)) {
5453                 status = WERR_BADFUNC;
5454                 goto out;
5455         }
5456
5457         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5458
5459         if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5460                 status = WERR_OK;
5461         } else {
5462                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5463                 status = WERR_BADFUNC;
5464         }
5465
5466         /* Free malloc'ed memory */
5467
5468  out:
5469
5470         if (prs_init_done) {
5471                 prs_mem_free(&ps);
5472         }
5473         if (mem_ctx)
5474                 talloc_destroy(mem_ctx);
5475         return status;
5476 }
5477
5478 /****************************************************************************
5479  Construct a default security descriptor buffer for a printer.
5480 ****************************************************************************/
5481
5482 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5483 {
5484         SEC_ACE ace[5]; /* max number of ace entries */
5485         int i = 0;
5486         SEC_ACCESS sa;
5487         SEC_ACL *psa = NULL;
5488         SEC_DESC_BUF *sdb = NULL;
5489         SEC_DESC *psd = NULL;
5490         DOM_SID adm_sid;
5491         size_t sd_size;
5492
5493         /* Create an ACE where Everyone is allowed to print */
5494
5495         init_sec_access(&sa, PRINTER_ACE_PRINT);
5496         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5497                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5498
5499         /* Add the domain admins group if we are a DC */
5500         
5501         if ( IS_DC ) {
5502                 DOM_SID domadmins_sid;
5503                 
5504                 sid_copy(&domadmins_sid, get_global_sam_sid());
5505                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5506                 
5507                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5508                 init_sec_ace(&ace[i++], &domadmins_sid, 
5509                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5510                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5511                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5512                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5513         }
5514         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5515                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5516
5517                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5518                 init_sec_ace(&ace[i++], &adm_sid, 
5519                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5520                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5521                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5522                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5523         }
5524
5525         /* add BUILTIN\Administrators as FULL CONTROL */
5526
5527         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5528         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5529                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5530                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5531         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5532                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5533                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5534
5535         /* Make the security descriptor owned by the BUILTIN\Administrators */
5536
5537         /* The ACL revision number in rpc_secdesc.h differs from the one
5538            created by NT when setting ACE entries in printer
5539            descriptors.  NT4 complains about the property being edited by a
5540            NT5 machine. */
5541
5542         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5543                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5544                         &global_sid_Builtin_Administrators, 
5545                         &global_sid_Builtin_Administrators,
5546                         NULL, psa, &sd_size);
5547         }
5548
5549         if (!psd) {
5550                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5551                 return NULL;
5552         }
5553
5554         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5555
5556         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5557                  (unsigned int)sd_size));
5558
5559         return sdb;
5560 }
5561
5562 /****************************************************************************
5563  Get a security desc for a printer.
5564 ****************************************************************************/
5565
5566 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5567 {
5568         prs_struct ps;
5569         TDB_DATA kbuf;
5570         char *temp;
5571
5572         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5573                 sharename = temp + 1;
5574         }
5575
5576         ZERO_STRUCT(ps);
5577
5578         /* Fetch security descriptor from tdb */
5579
5580         kbuf = make_printers_secdesc_tdbkey(ctx, sharename  );
5581
5582         if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5583             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5584
5585                 prs_mem_free(&ps);
5586
5587                 DEBUG(4,("using default secdesc for %s\n", sharename));
5588
5589                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5590                         return False;
5591                 }
5592
5593                 /* Save default security descriptor for later */
5594
5595                 if (!prs_init(&ps, (uint32)ndr_size_security_descriptor((*secdesc_ctr)->sd, 0) +
5596                         sizeof(SEC_DESC_BUF), ctx, MARSHALL))
5597                         return False;
5598
5599                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5600                         tdb_prs_store(tdb_printers, kbuf, &ps);
5601                 }
5602
5603                 prs_mem_free(&ps);
5604
5605                 return True;
5606         }
5607
5608         prs_mem_free(&ps);
5609
5610         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5611            this security descriptor has been created when winbindd was
5612            down.  Take ownership of security descriptor. */
5613
5614         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5615                 DOM_SID owner_sid;
5616
5617                 /* Change sd owner to workgroup administrator */
5618
5619                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5620                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5621                         SEC_DESC *psd = NULL;
5622                         size_t size;
5623
5624                         /* Create new sd */
5625
5626                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5627
5628                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5629                                             &owner_sid,
5630                                             (*secdesc_ctr)->sd->group_sid,
5631                                             (*secdesc_ctr)->sd->sacl,
5632                                             (*secdesc_ctr)->sd->dacl,
5633                                             &size);
5634
5635                         if (!psd) {
5636                                 return False;
5637                         }
5638
5639                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5640                         if (!new_secdesc_ctr) {
5641                                 return False;
5642                         }
5643
5644                         /* Swap with other one */
5645
5646                         *secdesc_ctr = new_secdesc_ctr;
5647
5648                         /* Set it */
5649
5650                         nt_printing_setsec(sharename, *secdesc_ctr);
5651                 }
5652         }
5653
5654         if (DEBUGLEVEL >= 10) {
5655                 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5656                 int i;
5657
5658                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5659                            sharename, the_acl->num_aces));
5660
5661                 for (i = 0; i < the_acl->num_aces; i++) {
5662                         DEBUG(10, ("%s %d %d 0x%08x\n",
5663                                    sid_string_dbg(&the_acl->aces[i].trustee),
5664                                    the_acl->aces[i].type, the_acl->aces[i].flags, 
5665                                    the_acl->aces[i].access_mask)); 
5666                 }
5667         }
5668
5669         return True;
5670 }
5671
5672 /* error code:
5673         0: everything OK
5674         1: level not implemented
5675         2: file doesn't exist
5676         3: can't allocate memory
5677         4: can't free memory
5678         5: non existant struct
5679 */
5680
5681 /*
5682         A printer and a printer driver are 2 different things.
5683         NT manages them separatelly, Samba does the same.
5684         Why ? Simply because it's easier and it makes sense !
5685         
5686         Now explanation: You have 3 printers behind your samba server,
5687         2 of them are the same make and model (laser A and B). But laser B
5688         has an 3000 sheet feeder and laser A doesn't such an option.
5689         Your third printer is an old dot-matrix model for the accounting :-).
5690         
5691         If the /usr/local/samba/lib directory (default dir), you will have
5692         5 files to describe all of this.
5693         
5694         3 files for the printers (1 by printer):
5695                 NTprinter_laser A
5696                 NTprinter_laser B
5697                 NTprinter_accounting
5698         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5699                 NTdriver_printer model X
5700                 NTdriver_printer model Y
5701
5702 jfm: I should use this comment for the text file to explain
5703         same thing for the forms BTW.
5704         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5705
5706 */
5707
5708 /* Convert generic access rights to printer object specific access rights.
5709    It turns out that NT4 security descriptors use generic access rights and
5710    NT5 the object specific ones. */
5711
5712 void map_printer_permissions(SEC_DESC *sd)
5713 {
5714         int i;
5715
5716         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5717                 se_map_generic(&sd->dacl->aces[i].access_mask,
5718                                &printer_generic_mapping);
5719         }
5720 }
5721
5722 /****************************************************************************
5723  Check a user has permissions to perform the given operation.  We use the
5724  permission constants defined in include/rpc_spoolss.h to check the various
5725  actions we perform when checking printer access.
5726
5727    PRINTER_ACCESS_ADMINISTER:
5728        print_queue_pause, print_queue_resume, update_printer_sec,
5729        update_printer, spoolss_addprinterex_level_2,
5730        _spoolss_setprinterdata
5731
5732    PRINTER_ACCESS_USE:
5733        print_job_start
5734
5735    JOB_ACCESS_ADMINISTER:
5736        print_job_delete, print_job_pause, print_job_resume,
5737        print_queue_purge
5738
5739   Try access control in the following order (for performance reasons):
5740     1)  root ans SE_PRINT_OPERATOR can do anything (easy check) 
5741     2)  check security descriptor (bit comparisons in memory)
5742     3)  "printer admins" (may result in numerous calls to winbind)
5743
5744  ****************************************************************************/
5745 bool print_access_check(struct current_user *user, int snum, int access_type)
5746 {
5747         SEC_DESC_BUF *secdesc = NULL;
5748         uint32 access_granted;
5749         NTSTATUS status;
5750         bool result;
5751         const char *pname;
5752         TALLOC_CTX *mem_ctx = NULL;
5753         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5754         
5755         /* If user is NULL then use the current_user structure */
5756
5757         if (!user)
5758                 user = &current_user;
5759
5760         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5761
5762         if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5763                 return True;
5764         }
5765
5766         /* Get printer name */
5767
5768         pname = PRINTERNAME(snum);
5769
5770         if (!pname || !*pname) {
5771                 errno = EACCES;
5772                 return False;
5773         }
5774
5775         /* Get printer security descriptor */
5776
5777         if(!(mem_ctx = talloc_init("print_access_check"))) {
5778                 errno = ENOMEM;
5779                 return False;
5780         }
5781
5782         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5783                 talloc_destroy(mem_ctx);
5784                 errno = ENOMEM;
5785                 return False;
5786         }
5787
5788         if (access_type == JOB_ACCESS_ADMINISTER) {
5789                 SEC_DESC_BUF *parent_secdesc = secdesc;
5790
5791                 /* Create a child security descriptor to check permissions
5792                    against.  This is because print jobs are child objects
5793                    objects of a printer. */
5794
5795                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5796
5797                 if (!secdesc) {
5798                         talloc_destroy(mem_ctx);
5799                         errno = ENOMEM;
5800                         return False;
5801                 }
5802
5803                 /* Now this is the bit that really confuses me.  The access
5804                    type needs to be changed from JOB_ACCESS_ADMINISTER to
5805                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
5806                    to do with the child (job) object becoming like a
5807                    printer??  -tpot */
5808
5809                 access_type = PRINTER_ACCESS_ADMINISTER;
5810         }
5811         
5812         /* Check access */
5813         
5814         map_printer_permissions(secdesc->sd);
5815
5816         result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5817                                  &access_granted, &status);
5818
5819         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5820
5821         /* see if we need to try the printer admin list */
5822
5823         if ((access_granted == 0) &&
5824             (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5825                                          user->nt_user_token,
5826                                          lp_printer_admin(snum)))) {
5827                 talloc_destroy(mem_ctx);
5828                 return True;
5829         }
5830
5831         talloc_destroy(mem_ctx);
5832         
5833         if (!result) {
5834                 errno = EACCES;
5835         }
5836
5837         return result;
5838 }
5839
5840 /****************************************************************************
5841  Check the time parameters allow a print operation.
5842 *****************************************************************************/
5843
5844 bool print_time_access_check(const char *servicename)
5845 {
5846         NT_PRINTER_INFO_LEVEL *printer = NULL;
5847         bool ok = False;
5848         time_t now = time(NULL);
5849         struct tm *t;
5850         uint32 mins;
5851
5852         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5853                 return False;
5854
5855         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5856                 ok = True;
5857
5858         t = gmtime(&now);
5859         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5860
5861         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5862                 ok = True;
5863
5864         free_a_printer(&printer, 2);
5865
5866         if (!ok)
5867                 errno = EACCES;
5868
5869         return ok;
5870 }
5871
5872 /****************************************************************************
5873  Fill in the servername sent in the _spoolss_open_printer_ex() call
5874 ****************************************************************************/
5875
5876 char* get_server_name( Printer_entry *printer )
5877 {
5878         return printer->servername;
5879 }
5880
5881