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