Merge branch 'master' into wspp-schema
[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), 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         NTSTATUS status;
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         status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
366         if (!NT_STATUS_IS_OK(status)) {
367                 /* delete bad entries */
368                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n",
369                         (const char *)key.dptr ));
370                 tdb_delete( tdb_printers, key );
371                 return 0;
372         }
373
374         if (!sd_orig) {
375                 return 0;
376         }
377         sec = sd_orig->sd;
378
379         /* is this even valid? */
380
381         if ( !sec->dacl ) {
382                 return 0;
383         }
384
385         /* update access masks */
386
387         for ( i=0; i<sec->dacl->num_aces; i++ ) {
388                 switch ( sec->dacl->aces[i].access_mask ) {
389                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
390                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
391                                 break;
392
393                         case GENERIC_ALL_ACCESS:
394                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
395                                 break;
396
397                         case READ_CONTROL_ACCESS:
398                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
399
400                         default:        /* no change */
401                                 break;
402                 }
403         }
404
405         /* create a new SEC_DESC with the appropriate owner and group SIDs */
406
407         new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
408                                  &global_sid_Builtin_Administrators,
409                                  &global_sid_Builtin_Administrators,
410                                  NULL, NULL, &size_new_sec );
411         if (!new_sec) {
412                 return 0;
413         }
414         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
415         if (!sd_new) {
416                 return 0;
417         }
418
419         if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
420                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
421                 return 0;
422         }
423
424         /* store it back */
425
426         sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0)
427                 + sizeof(SEC_DESC_BUF);
428
429         status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
430         if (!NT_STATUS_IS_OK(status)) {
431                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
432                 return 0;
433         }
434
435         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
436
437         /* 0 to continue and non-zero to stop traversal */
438
439         return (result == -1);
440 }
441
442 /*******************************************************************
443 *******************************************************************/
444
445 static bool upgrade_to_version_4(void)
446 {
447         TALLOC_CTX *ctx;
448         int result;
449
450         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
451
452         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
453                 return False;
454
455         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
456
457         talloc_destroy( ctx );
458
459         return ( result != -1 );
460 }
461
462 /*******************************************************************
463  Fix an issue with security descriptors.  Printer sec_desc must
464  use more than the generic bits that were previously used
465  in <= 3.0.14a.  They must also have a owner and group SID assigned.
466  Otherwise, any printers than have been migrated to a Windows
467  host using printmig.exe will not be accessible.
468 *******************************************************************/
469
470 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
471                                   TDB_DATA data, void *state )
472 {
473         TALLOC_CTX *ctx = talloc_tos();
474         TDB_DATA new_key;
475
476         if (!data.dptr || data.dsize == 0)
477                 return 0;
478
479         /* upgrade printer records and security descriptors */
480
481         if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
482                 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
483         }
484         else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
485                 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
486         }
487         else {
488                 /* ignore this record */
489                 return 0;
490         }
491
492         /* delete the original record and store under the normalized key */
493
494         if ( tdb_delete( the_tdb, key ) != 0 ) {
495                 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
496                         key.dptr));
497                 return 1;
498         }
499
500         if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
501                 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
502                         key.dptr));
503                 return 1;
504         }
505
506         return 0;
507 }
508
509 /*******************************************************************
510 *******************************************************************/
511
512 static bool upgrade_to_version_5(void)
513 {
514         TALLOC_CTX *ctx;
515         int result;
516
517         DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
518
519         if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
520                 return False;
521
522         result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
523
524         talloc_destroy( ctx );
525
526         return ( result != -1 );
527 }
528
529 /****************************************************************************
530  Open the NT printing tdbs. Done once before fork().
531 ****************************************************************************/
532
533 bool nt_printing_init(struct messaging_context *msg_ctx)
534 {
535         const char *vstring = "INFO/version";
536         WERROR win_rc;
537         int32 vers_id;
538
539         if ( tdb_drivers && tdb_printers && tdb_forms )
540                 return True;
541
542         if (tdb_drivers)
543                 tdb_close(tdb_drivers);
544         tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
545         if (!tdb_drivers) {
546                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
547                         state_path("ntdrivers.tdb"), strerror(errno) ));
548                 return False;
549         }
550
551         if (tdb_printers)
552                 tdb_close(tdb_printers);
553         tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
554         if (!tdb_printers) {
555                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
556                         state_path("ntprinters.tdb"), strerror(errno) ));
557                 return False;
558         }
559
560         if (tdb_forms)
561                 tdb_close(tdb_forms);
562         tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
563         if (!tdb_forms) {
564                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
565                         state_path("ntforms.tdb"), strerror(errno) ));
566                 return False;
567         }
568
569         /* handle a Samba upgrade */
570
571         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
572         if (vers_id == -1) {
573                 DEBUG(10, ("Fresh database\n"));
574                 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
575                 vers_id = NTDRIVERS_DATABASE_VERSION_5;
576         }
577
578         if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
579
580                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
581                         if (!upgrade_to_version_3())
582                                 return False;
583                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
584                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
585                 }
586
587                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
588                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
589                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
590                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
591                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
592                 }
593
594                 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
595                         if ( !upgrade_to_version_4() )
596                                 return False;
597                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
598                         vers_id = NTDRIVERS_DATABASE_VERSION_4;
599                 }
600
601                 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
602                         if ( !upgrade_to_version_5() )
603                                 return False;
604                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
605                         vers_id = NTDRIVERS_DATABASE_VERSION_5;
606                 }
607
608
609                 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
610                         DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
611                         return False;
612                 }
613         }
614
615         update_c_setprinter(True);
616
617         /*
618          * register callback to handle updating printers as new
619          * drivers are installed
620          */
621
622         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
623                            do_drv_upgrade_printer);
624
625         /*
626          * register callback to handle updating printer data
627          * when a driver is initialized
628          */
629
630         messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
631                            reset_all_printerdata);
632
633         /* of course, none of the message callbacks matter if you don't
634            tell messages.c that you interested in receiving PRINT_GENERAL
635            msgs.  This is done in claim_connection() */
636
637
638         if ( lp_security() == SEC_ADS ) {
639                 win_rc = check_published_printers();
640                 if (!W_ERROR_IS_OK(win_rc))
641                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
642         }
643
644         return True;
645 }
646
647 /*******************************************************************
648  Function to allow filename parsing "the old way".
649 ********************************************************************/
650
651 static char *driver_unix_convert(connection_struct *conn,
652                 const char *old_name,
653                 SMB_STRUCT_STAT *pst)
654 {
655         TALLOC_CTX *ctx = talloc_tos();
656         char *name = talloc_strdup(ctx, old_name);
657         char *new_name = NULL;
658
659         if (!name) {
660                 return NULL;
661         }
662         unix_format(name);
663         name = unix_clean_name(ctx, name);
664         if (!name) {
665                 return NULL;
666         }
667         trim_string(name,"/","/");
668         unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
669         return new_name;
670 }
671
672 /*******************************************************************
673  tdb traversal function for counting printers.
674 ********************************************************************/
675
676 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
677                                       TDB_DATA data, void *context)
678 {
679         int *printer_count = (int*)context;
680
681         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
682                 (*printer_count)++;
683                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
684         }
685
686         return 0;
687 }
688
689 /*******************************************************************
690  Update the spooler global c_setprinter. This variable is initialized
691  when the parent smbd starts with the number of existing printers. It
692  is monotonically increased by the current number of printers *after*
693  each add or delete printer RPC. Only Microsoft knows why... JRR020119
694 ********************************************************************/
695
696 uint32 update_c_setprinter(bool initialize)
697 {
698         int32 c_setprinter;
699         int32 printer_count = 0;
700
701         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
702
703         /* Traverse the tdb, counting the printers */
704         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
705
706         /* If initializing, set c_setprinter to current printers count
707          * otherwise, bump it by the current printer count
708          */
709         if (!initialize)
710                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
711         else
712                 c_setprinter = printer_count;
713
714         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
715         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
716
717         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
718
719         return (uint32)c_setprinter;
720 }
721
722 /*******************************************************************
723  Get the spooler global c_setprinter, accounting for initialization.
724 ********************************************************************/
725
726 uint32 get_c_setprinter(void)
727 {
728         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
729
730         if (c_setprinter == (int32)-1)
731                 c_setprinter = update_c_setprinter(True);
732
733         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
734
735         return (uint32)c_setprinter;
736 }
737
738 /****************************************************************************
739  Get builtin form struct list.
740 ****************************************************************************/
741
742 int get_builtin_ntforms(nt_forms_struct **list)
743 {
744         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
745         if (!*list) {
746                 return 0;
747         }
748         return sizeof(default_forms) / sizeof(default_forms[0]);
749 }
750
751 /****************************************************************************
752  get a builtin form struct
753 ****************************************************************************/
754
755 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
756 {
757         int i,count;
758         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
759         count = sizeof(default_forms) / sizeof(default_forms[0]);
760         for (i=0;i<count;i++) {
761                 if (strequal(form_name,default_forms[i].name)) {
762                         DEBUGADD(6,("Found builtin form %s \n", form_name));
763                         memcpy(form,&default_forms[i],sizeof(*form));
764                         break;
765                 }
766         }
767
768         return (i !=count);
769 }
770
771 /****************************************************************************
772  get a form struct list.
773 ****************************************************************************/
774
775 int get_ntforms(nt_forms_struct **list)
776 {
777         TDB_DATA kbuf, newkey, dbuf;
778         nt_forms_struct form;
779         int ret;
780         int i;
781         int n = 0;
782
783         *list = NULL;
784
785         for (kbuf = tdb_firstkey(tdb_forms);
786              kbuf.dptr;
787              newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
788         {
789                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
790                         continue;
791
792                 dbuf = tdb_fetch(tdb_forms, kbuf);
793                 if (!dbuf.dptr)
794                         continue;
795
796                 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
797                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
798                                  &i, &form.flag, &form.width, &form.length, &form.left,
799                                  &form.top, &form.right, &form.bottom);
800                 SAFE_FREE(dbuf.dptr);
801                 if (ret != dbuf.dsize)
802                         continue;
803
804                 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
805                 if (!*list) {
806                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
807                         return 0;
808                 }
809                 (*list)[n] = form;
810                 n++;
811         }
812
813
814         return n;
815 }
816
817 /****************************************************************************
818 write a form struct list
819 ****************************************************************************/
820
821 int write_ntforms(nt_forms_struct **list, int number)
822 {
823         TALLOC_CTX *ctx = talloc_tos();
824         char *buf = NULL;
825         char *key = NULL;
826         int len;
827         TDB_DATA dbuf;
828         int i;
829
830         for (i=0;i<number;i++) {
831                 /* save index, so list is rebuilt in correct order */
832                 len = tdb_pack(NULL, 0, "dddddddd",
833                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
834                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
835                                (*list)[i].bottom);
836                 if (!len) {
837                         continue;
838                 }
839                 buf = TALLOC_ARRAY(ctx, char, len);
840                 if (!buf) {
841                         return 0;
842                 }
843                 len = tdb_pack((uint8 *)buf, len, "dddddddd",
844                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
845                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
846                                (*list)[i].bottom);
847                 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
848                 if (!key) {
849                         return 0;
850                 }
851                 dbuf.dsize = len;
852                 dbuf.dptr = (uint8 *)buf;
853                 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
854                         TALLOC_FREE(key);
855                         TALLOC_FREE(buf);
856                         break;
857                 }
858                 TALLOC_FREE(key);
859                 TALLOC_FREE(buf);
860        }
861
862        return i;
863 }
864
865 /****************************************************************************
866 add a form struct at the end of the list
867 ****************************************************************************/
868 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
869 {
870         int n=0;
871         bool update;
872
873         /*
874          * NT tries to add forms even when
875          * they are already in the base
876          * only update the values if already present
877          */
878
879         update=False;
880
881         for (n=0; n<*count; n++) {
882                 if ( strequal((*list)[n].name, form->form_name) ) {
883                         update=True;
884                         break;
885                 }
886         }
887
888         if (update==False) {
889                 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
890                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
891                         return False;
892                 }
893                 fstrcpy((*list)[n].name, form->form_name);
894                 (*count)++;
895         }
896
897         (*list)[n].flag         = form->flags;
898         (*list)[n].width        = form->size.width;
899         (*list)[n].length       = form->size.height;
900         (*list)[n].left         = form->area.left;
901         (*list)[n].top          = form->area.top;
902         (*list)[n].right        = form->area.right;
903         (*list)[n].bottom       = form->area.bottom;
904
905         DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
906                 update ? "updated" : "added", form->form_name));
907
908         return True;
909 }
910
911 /****************************************************************************
912  Delete a named form struct.
913 ****************************************************************************/
914
915 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
916 {
917         char *key = NULL;
918         int n=0;
919
920         *ret = WERR_OK;
921
922         for (n=0; n<*count; n++) {
923                 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
924                         DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
925                         break;
926                 }
927         }
928
929         if (n == *count) {
930                 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
931                 *ret = WERR_INVALID_PARAM;
932                 return False;
933         }
934
935         if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
936                 *ret = WERR_NOMEM;
937                 return false;
938         }
939         if (tdb_delete_bystring(tdb_forms, key) != 0) {
940                 SAFE_FREE(key);
941                 *ret = WERR_NOMEM;
942                 return False;
943         }
944         SAFE_FREE(key);
945         return true;
946 }
947
948 /****************************************************************************
949  Update a form struct.
950 ****************************************************************************/
951
952 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
953 {
954         int n=0;
955
956         DEBUG(106, ("[%s]\n", form->form_name));
957         for (n=0; n<count; n++) {
958                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
959                 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
960                         break;
961         }
962
963         if (n==count) return;
964
965         (*list)[n].flag         = form->flags;
966         (*list)[n].width        = form->size.width;
967         (*list)[n].length       = form->size.height;
968         (*list)[n].left         = form->area.left;
969         (*list)[n].top          = form->area.top;
970         (*list)[n].right        = form->area.right;
971         (*list)[n].bottom       = form->area.bottom;
972 }
973
974 /****************************************************************************
975  Get the nt drivers list.
976  Traverse the database and look-up the matching names.
977 ****************************************************************************/
978 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
979 {
980         int total=0;
981         const char *short_archi;
982         char *key = NULL;
983         TDB_DATA kbuf, newkey;
984
985         short_archi = get_short_archi(architecture);
986         if (!short_archi) {
987                 return 0;
988         }
989
990         if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
991                                 short_archi, version) < 0) {
992                 return 0;
993         }
994
995         for (kbuf = tdb_firstkey(tdb_drivers);
996              kbuf.dptr;
997              newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
998
999                 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
1000                         continue;
1001
1002                 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
1003                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
1004                         SAFE_FREE(key);
1005                         return -1;
1006                 }
1007
1008                 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1009                 total++;
1010         }
1011
1012         SAFE_FREE(key);
1013         return(total);
1014 }
1015
1016 /****************************************************************************
1017  Function to do the mapping between the long architecture name and
1018  the short one.
1019 ****************************************************************************/
1020
1021 const char *get_short_archi(const char *long_archi)
1022 {
1023         int i=-1;
1024
1025         DEBUG(107,("Getting architecture dependant directory\n"));
1026         do {
1027                 i++;
1028         } while ( (archi_table[i].long_archi!=NULL ) &&
1029                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
1030
1031         if (archi_table[i].long_archi==NULL) {
1032                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1033                 return NULL;
1034         }
1035
1036         /* this might be client code - but shouldn't this be an fstrcpy etc? */
1037
1038         DEBUGADD(108,("index: [%d]\n", i));
1039         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1040         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1041
1042         return archi_table[i].short_archi;
1043 }
1044
1045 /****************************************************************************
1046  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1047  There are two case to be covered here: PE (Portable Executable) and NE (New
1048  Executable) files. Both files support the same INFO structure, but PE files
1049  store the signature in unicode, and NE files store it as !unicode.
1050  returns -1 on error, 1 on version info found, and 0 on no version info found.
1051 ****************************************************************************/
1052
1053 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1054 {
1055         int     i;
1056         char    *buf = NULL;
1057         ssize_t byte_count;
1058
1059         if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1060                 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1061                                 fname, DOS_HEADER_SIZE));
1062                 goto error_exit;
1063         }
1064
1065         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1066                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1067                          fname, (unsigned long)byte_count));
1068                 goto no_version_info;
1069         }
1070
1071         /* Is this really a DOS header? */
1072         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1073                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1074                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1075                 goto no_version_info;
1076         }
1077
1078         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1079         if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1080                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1081                                 fname, errno));
1082                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1083                 goto no_version_info;
1084         }
1085
1086         /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1087         if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1088                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1089                          fname, (unsigned long)byte_count));
1090                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1091                 goto no_version_info;
1092         }
1093
1094         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1095         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1096                 unsigned int num_sections;
1097                 unsigned int section_table_bytes;
1098
1099                 /* Just skip over optional header to get to section table */
1100                 if (SMB_VFS_LSEEK(fsp,
1101                                 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1102                                 SEEK_CUR) == (SMB_OFF_T)-1) {
1103                         DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1104                                 fname, errno));
1105                         goto error_exit;
1106                 }
1107
1108                 /* get the section table */
1109                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1110                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1111                 if (section_table_bytes == 0)
1112                         goto error_exit;
1113
1114                 SAFE_FREE(buf);
1115                 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1116                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1117                                         fname, section_table_bytes));
1118                         goto error_exit;
1119                 }
1120
1121                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1122                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1123                                  fname, (unsigned long)byte_count));
1124                         goto error_exit;
1125                 }
1126
1127                 /* Iterate the section table looking for the resource section ".rsrc" */
1128                 for (i = 0; i < num_sections; i++) {
1129                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1130
1131                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1132                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1133                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1134
1135                                 if (section_bytes == 0)
1136                                         goto error_exit;
1137
1138                                 SAFE_FREE(buf);
1139                                 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1140                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1141                                                         fname, section_bytes));
1142                                         goto error_exit;
1143                                 }
1144
1145                                 /* Seek to the start of the .rsrc section info */
1146                                 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1147                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1148                                                         fname, errno));
1149                                         goto error_exit;
1150                                 }
1151
1152                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1153                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1154                                                  fname, (unsigned long)byte_count));
1155                                         goto error_exit;
1156                                 }
1157
1158                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1159                                         goto error_exit;
1160
1161                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1162                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1163                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1164                                                 /* Align to next long address */
1165                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1166
1167                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1168                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1169                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1170
1171                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1172                                                                           fname, *major, *minor,
1173                                                                           (*major>>16)&0xffff, *major&0xffff,
1174                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1175                                                         SAFE_FREE(buf);
1176                                                         return 1;
1177                                                 }
1178                                         }
1179                                 }
1180                         }
1181                 }
1182
1183                 /* Version info not found, fall back to origin date/time */
1184                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1185                 SAFE_FREE(buf);
1186                 return 0;
1187
1188         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1189                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1190                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1191                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1192                         /* At this point, we assume the file is in error. It still could be somthing
1193                          * else besides a NE file, but it unlikely at this point. */
1194                         goto error_exit;
1195                 }
1196
1197                 /* Allocate a bit more space to speed up things */
1198                 SAFE_FREE(buf);
1199                 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1200                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1201                                         fname, PE_HEADER_SIZE));
1202                         goto error_exit;
1203                 }
1204
1205                 /* This is a HACK! I got tired of trying to sort through the messy
1206                  * 'NE' file format. If anyone wants to clean this up please have at
1207                  * it, but this works. 'NE' files will eventually fade away. JRR */
1208                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1209                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1210                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1211
1212                         for(i=0; i<byte_count; i++) {
1213                                 /* Fast skip past data that can't possibly match */
1214                                 if (buf[i] != 'V') continue;
1215
1216                                 /* Potential match data crosses buf boundry, move it to beginning
1217                                  * of buf, and fill the buf with as much as it will hold. */
1218                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1219                                         int bc;
1220
1221                                         memcpy(buf, &buf[i], byte_count-i);
1222                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1223                                                                    (byte_count-i))) < 0) {
1224
1225                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1226                                                                  fname, errno));
1227                                                 goto error_exit;
1228                                         }
1229
1230                                         byte_count = bc + (byte_count - i);
1231                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1232
1233                                         i = 0;
1234                                 }
1235
1236                                 /* Check that the full signature string and the magic number that
1237                                  * follows exist (not a perfect solution, but the chances that this
1238                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1239                                  * twice, as it is simpler to read the code. */
1240                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1241                                         /* Compute skip alignment to next long address */
1242                                         int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1243                                                                  sizeof(VS_SIGNATURE)) & 3;
1244                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1245
1246                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1247                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1248                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1249                                                           fname, *major, *minor,
1250                                                           (*major>>16)&0xffff, *major&0xffff,
1251                                                           (*minor>>16)&0xffff, *minor&0xffff));
1252                                         SAFE_FREE(buf);
1253                                         return 1;
1254                                 }
1255                         }
1256                 }
1257
1258                 /* Version info not found, fall back to origin date/time */
1259                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1260                 SAFE_FREE(buf);
1261                 return 0;
1262
1263         } else
1264                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1265                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1266                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1267
1268         no_version_info:
1269                 SAFE_FREE(buf);
1270                 return 0;
1271
1272         error_exit:
1273                 SAFE_FREE(buf);
1274                 return -1;
1275 }
1276
1277 /****************************************************************************
1278 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1279 share one or more files. During the MS installation process files are checked
1280 to insure that only a newer version of a shared file is installed over an
1281 older version. There are several possibilities for this comparison. If there
1282 is no previous version, the new one is newer (obviously). If either file is
1283 missing the version info structure, compare the creation date (on Unix use
1284 the modification date). Otherwise chose the numerically larger version number.
1285 ****************************************************************************/
1286
1287 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1288 {
1289         bool use_version = true;
1290         char *filepath = NULL;
1291
1292         uint32 new_major;
1293         uint32 new_minor;
1294         time_t new_create_time;
1295
1296         uint32 old_major;
1297         uint32 old_minor;
1298         time_t old_create_time;
1299
1300         files_struct    *fsp = NULL;
1301         SMB_STRUCT_STAT st;
1302         SMB_STRUCT_STAT stat_buf;
1303
1304         NTSTATUS status;
1305
1306         SET_STAT_INVALID(st);
1307         SET_STAT_INVALID(stat_buf);
1308         new_create_time = (time_t)0;
1309         old_create_time = (time_t)0;
1310
1311         /* Get file version info (if available) for previous file (if it exists) */
1312         filepath = driver_unix_convert(conn,old_file,&stat_buf);
1313         if (!filepath) {
1314                 goto error_exit;
1315         }
1316
1317         status = SMB_VFS_CREATE_FILE(
1318                 conn,                                   /* conn */
1319                 NULL,                                   /* req */
1320                 0,                                      /* root_dir_fid */
1321                 filepath,                               /* fname */
1322                 0,                                      /* create_file_flags */
1323                 FILE_GENERIC_READ,                      /* access_mask */
1324                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1325                 FILE_OPEN,                              /* create_disposition*/
1326                 0,                                      /* create_options */
1327                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1328                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1329                 0,                                      /* allocation_size */
1330                 NULL,                                   /* sd */
1331                 NULL,                                   /* ea_list */
1332                 &fsp,                                   /* result */
1333                 NULL,                                   /* pinfo */
1334                 &stat_buf);                             /* psbuf */
1335
1336         if (!NT_STATUS_IS_OK(status)) {
1337                 /* Old file not found, so by definition new file is in fact newer */
1338                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1339                                 filepath, errno));
1340                 return 1;
1341
1342         } else {
1343                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1344                 if (ret == -1) {
1345                         goto error_exit;
1346                 }
1347
1348                 if (!ret) {
1349                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1350                                          old_file));
1351                         use_version = false;
1352                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1353                                  goto error_exit;
1354                         }
1355                         old_create_time = st.st_mtime;
1356                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1357                                 (long)old_create_time));
1358                 }
1359         }
1360         close_file(NULL, fsp, NORMAL_CLOSE);
1361         fsp = NULL;
1362
1363         /* Get file version info (if available) for new file */
1364         filepath = driver_unix_convert(conn,new_file,&stat_buf);
1365         if (!filepath) {
1366                 goto error_exit;
1367         }
1368
1369         status = SMB_VFS_CREATE_FILE(
1370                 conn,                                   /* conn */
1371                 NULL,                                   /* req */
1372                 0,                                      /* root_dir_fid */
1373                 filepath,                               /* fname */
1374                 0,                                      /* create_file_flags */
1375                 FILE_GENERIC_READ,                      /* access_mask */
1376                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1377                 FILE_OPEN,                              /* create_disposition*/
1378                 0,                                      /* create_options */
1379                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1380                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1381                 0,                                      /* allocation_size */
1382                 NULL,                                   /* sd */
1383                 NULL,                                   /* ea_list */
1384                 &fsp,                                   /* result */
1385                 NULL,                                   /* pinfo */
1386                 &stat_buf);                             /* psbuf */
1387
1388         if (!NT_STATUS_IS_OK(status)) {
1389                 /* New file not found, this shouldn't occur if the caller did its job */
1390                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1391                                 filepath, errno));
1392                 goto error_exit;
1393
1394         } else {
1395                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1396                 if (ret == -1) {
1397                         goto error_exit;
1398                 }
1399
1400                 if (!ret) {
1401                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1402                                          new_file));
1403                         use_version = false;
1404                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1405                                 goto error_exit;
1406                         }
1407                         new_create_time = st.st_mtime;
1408                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1409                                 (long)new_create_time));
1410                 }
1411         }
1412         close_file(NULL, fsp, NORMAL_CLOSE);
1413         fsp = NULL;
1414
1415         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1416                 /* Compare versions and choose the larger version number */
1417                 if (new_major > old_major ||
1418                         (new_major == old_major && new_minor > old_minor)) {
1419
1420                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1421                         return 1;
1422                 }
1423                 else {
1424                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1425                         return 0;
1426                 }
1427
1428         } else {
1429                 /* Compare modification time/dates and choose the newest time/date */
1430                 if (new_create_time > old_create_time) {
1431                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1432                         return 1;
1433                 }
1434                 else {
1435                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1436                         return 0;
1437                 }
1438         }
1439
1440         error_exit:
1441                 if(fsp)
1442                         close_file(NULL, fsp, NORMAL_CLOSE);
1443                 return -1;
1444 }
1445
1446 /****************************************************************************
1447 Determine the correct cVersion associated with an architecture and driver
1448 ****************************************************************************/
1449 static uint32 get_correct_cversion(struct pipes_struct *p,
1450                                    const char *architecture,
1451                                    fstring driverpath_in,
1452                                    WERROR *perr)
1453 {
1454         int               cversion;
1455         NTSTATUS          nt_status;
1456         char *driverpath = NULL;
1457         files_struct      *fsp = NULL;
1458         SMB_STRUCT_STAT   st;
1459         connection_struct *conn = NULL;
1460         NTSTATUS status;
1461         char *oldcwd;
1462         fstring printdollar;
1463         int printdollar_snum;
1464
1465         SET_STAT_INVALID(st);
1466
1467         *perr = WERR_INVALID_PARAM;
1468
1469         /* If architecture is Windows 95/98/ME, the version is always 0. */
1470         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1471                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1472                 *perr = WERR_OK;
1473                 return 0;
1474         }
1475
1476         /* If architecture is Windows x64, the version is always 3. */
1477         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1478                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1479                 *perr = WERR_OK;
1480                 return 3;
1481         }
1482
1483         fstrcpy(printdollar, "print$");
1484
1485         printdollar_snum = find_service(printdollar);
1486         if (printdollar_snum == -1) {
1487                 *perr = WERR_NO_SUCH_SHARE;
1488                 return -1;
1489         }
1490
1491         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1492                                        lp_pathname(printdollar_snum),
1493                                        p->server_info, &oldcwd);
1494         if (!NT_STATUS_IS_OK(nt_status)) {
1495                 DEBUG(0,("get_correct_cversion: create_conn_struct "
1496                          "returned %s\n", nt_errstr(nt_status)));
1497                 *perr = ntstatus_to_werror(nt_status);
1498                 return -1;
1499         }
1500
1501         /* Open the driver file (Portable Executable format) and determine the
1502          * deriver the cversion. */
1503         driverpath = talloc_asprintf(talloc_tos(),
1504                                         "%s/%s",
1505                                         architecture,
1506                                         driverpath_in);
1507         if (!driverpath) {
1508                 *perr = WERR_NOMEM;
1509                 goto error_exit;
1510         }
1511
1512         driverpath = driver_unix_convert(conn,driverpath,&st);
1513         if (!driverpath) {
1514                 *perr = WERR_NOMEM;
1515                 goto error_exit;
1516         }
1517
1518         if (!vfs_file_exist(conn, driverpath, &st)) {
1519                 *perr = WERR_BADFILE;
1520                 goto error_exit;
1521         }
1522
1523         status = SMB_VFS_CREATE_FILE(
1524                 conn,                                   /* conn */
1525                 NULL,                                   /* req */
1526                 0,                                      /* root_dir_fid */
1527                 driverpath,                             /* fname */
1528                 0,                                      /* create_file_flags */
1529                 FILE_GENERIC_READ,                      /* access_mask */
1530                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1531                 FILE_OPEN,                              /* create_disposition*/
1532                 0,                                      /* create_options */
1533                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1534                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1535                 0,                                      /* allocation_size */
1536                 NULL,                                   /* sd */
1537                 NULL,                                   /* ea_list */
1538                 &fsp,                                   /* result */
1539                 NULL,                                   /* pinfo */
1540                 &st);                                   /* psbuf */
1541
1542         if (!NT_STATUS_IS_OK(status)) {
1543                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1544                                 driverpath, errno));
1545                 *perr = WERR_ACCESS_DENIED;
1546                 goto error_exit;
1547         } else {
1548                 uint32 major;
1549                 uint32 minor;
1550                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1551                 if (ret == -1) goto error_exit;
1552
1553                 if (!ret) {
1554                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1555                         goto error_exit;
1556                 }
1557
1558                 /*
1559                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1560                  * for more details. Version in this case is not just the version of the
1561                  * file, but the version in the sense of kernal mode (2) vs. user mode
1562                  * (3) drivers. Other bits of the version fields are the version info.
1563                  * JRR 010716
1564                 */
1565                 cversion = major & 0x0000ffff;
1566                 switch (cversion) {
1567                         case 2: /* WinNT drivers */
1568                         case 3: /* Win2K drivers */
1569                                 break;
1570
1571                         default:
1572                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n",
1573                                         driverpath, cversion));
1574                                 goto error_exit;
1575                 }
1576
1577                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1578                                   driverpath, major, minor));
1579         }
1580
1581         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1582                 driverpath, cversion));
1583
1584         goto done;
1585
1586  error_exit:
1587         cversion = -1;
1588  done:
1589         if (fsp != NULL) {
1590                 close_file(NULL, fsp, NORMAL_CLOSE);
1591         }
1592         if (conn != NULL) {
1593                 vfs_ChDir(conn, oldcwd);
1594                 conn_free_internal(conn);
1595         }
1596         if (cversion != -1) {
1597                 *perr = WERR_OK;
1598         }
1599         return cversion;
1600 }
1601
1602 /****************************************************************************
1603 ****************************************************************************/
1604 static WERROR clean_up_driver_struct_level_3(struct pipes_struct *rpc_pipe,
1605                                              NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1606 {
1607         const char *architecture;
1608         fstring new_name;
1609         char *p;
1610         int i;
1611         WERROR err;
1612
1613         /* clean up the driver name.
1614          * we can get .\driver.dll
1615          * or worse c:\windows\system\driver.dll !
1616          */
1617         /* using an intermediate string to not have overlaping memcpy()'s */
1618         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1619                 fstrcpy(new_name, p+1);
1620                 fstrcpy(driver->driverpath, new_name);
1621         }
1622
1623         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1624                 fstrcpy(new_name, p+1);
1625                 fstrcpy(driver->datafile, new_name);
1626         }
1627
1628         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1629                 fstrcpy(new_name, p+1);
1630                 fstrcpy(driver->configfile, new_name);
1631         }
1632
1633         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1634                 fstrcpy(new_name, p+1);
1635                 fstrcpy(driver->helpfile, new_name);
1636         }
1637
1638         if (driver->dependentfiles) {
1639                 for (i=0; *driver->dependentfiles[i]; i++) {
1640                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1641                                 fstrcpy(new_name, p+1);
1642                                 fstrcpy(driver->dependentfiles[i], new_name);
1643                         }
1644                 }
1645         }
1646
1647         architecture = get_short_archi(driver->environment);
1648         if (!architecture) {
1649                 return WERR_UNKNOWN_PRINTER_DRIVER;
1650         }
1651
1652         /* jfm:7/16/2000 the client always sends the cversion=0.
1653          * The server should check which version the driver is by reading
1654          * the PE header of driver->driverpath.
1655          *
1656          * For Windows 95/98 the version is 0 (so the value sent is correct)
1657          * For Windows NT (the architecture doesn't matter)
1658          *      NT 3.1: cversion=0
1659          *      NT 3.5/3.51: cversion=1
1660          *      NT 4: cversion=2
1661          *      NT2K: cversion=3
1662          */
1663         if ((driver->cversion = get_correct_cversion(rpc_pipe, architecture,
1664                                                      driver->driverpath,
1665                                                      &err)) == -1)
1666                 return err;
1667
1668         return WERR_OK;
1669 }
1670
1671 /****************************************************************************
1672 ****************************************************************************/
1673 static WERROR clean_up_driver_struct_level_6(struct pipes_struct *rpc_pipe,
1674                                              NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1675 {
1676         const char *architecture;
1677         fstring new_name;
1678         char *p;
1679         int i;
1680         WERROR err;
1681
1682         /* clean up the driver name.
1683          * we can get .\driver.dll
1684          * or worse c:\windows\system\driver.dll !
1685          */
1686         /* using an intermediate string to not have overlaping memcpy()'s */
1687         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1688                 fstrcpy(new_name, p+1);
1689                 fstrcpy(driver->driverpath, new_name);
1690         }
1691
1692         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1693                 fstrcpy(new_name, p+1);
1694                 fstrcpy(driver->datafile, new_name);
1695         }
1696
1697         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1698                 fstrcpy(new_name, p+1);
1699                 fstrcpy(driver->configfile, new_name);
1700         }
1701
1702         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1703                 fstrcpy(new_name, p+1);
1704                 fstrcpy(driver->helpfile, new_name);
1705         }
1706
1707         if (driver->dependentfiles) {
1708                 for (i=0; *driver->dependentfiles[i]; i++) {
1709                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1710                                 fstrcpy(new_name, p+1);
1711                                 fstrcpy(driver->dependentfiles[i], new_name);
1712                         }
1713                 }
1714         }
1715
1716         architecture = get_short_archi(driver->environment);
1717         if (!architecture) {
1718                 return WERR_UNKNOWN_PRINTER_DRIVER;
1719         }
1720
1721         /* jfm:7/16/2000 the client always sends the cversion=0.
1722          * The server should check which version the driver is by reading
1723          * the PE header of driver->driverpath.
1724          *
1725          * For Windows 95/98 the version is 0 (so the value sent is correct)
1726          * For Windows NT (the architecture doesn't matter)
1727          *      NT 3.1: cversion=0
1728          *      NT 3.5/3.51: cversion=1
1729          *      NT 4: cversion=2
1730          *      NT2K: cversion=3
1731          */
1732
1733         if ((driver->version = get_correct_cversion(rpc_pipe, architecture,
1734                                                     driver->driverpath,
1735                                                     &err)) == -1)
1736                         return err;
1737
1738         return WERR_OK;
1739 }
1740
1741 /****************************************************************************
1742 ****************************************************************************/
1743 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
1744                               NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1745                               uint32 level)
1746 {
1747         switch (level) {
1748                 case 3:
1749                 {
1750                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1751                         driver=driver_abstract.info_3;
1752                         return clean_up_driver_struct_level_3(rpc_pipe,
1753                                                               driver);
1754                 }
1755                 case 6:
1756                 {
1757                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1758                         driver=driver_abstract.info_6;
1759                         return clean_up_driver_struct_level_6(rpc_pipe,
1760                                                               driver);
1761                 }
1762                 default:
1763                         return WERR_INVALID_PARAM;
1764         }
1765 }
1766
1767 /****************************************************************************
1768  This function sucks and should be replaced. JRA.
1769 ****************************************************************************/
1770
1771 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1772 {
1773     dst->cversion  = src->version;
1774
1775     fstrcpy( dst->name, src->name);
1776     fstrcpy( dst->environment, src->environment);
1777     fstrcpy( dst->driverpath, src->driverpath);
1778     fstrcpy( dst->datafile, src->datafile);
1779     fstrcpy( dst->configfile, src->configfile);
1780     fstrcpy( dst->helpfile, src->helpfile);
1781     fstrcpy( dst->monitorname, src->monitorname);
1782     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1783     dst->dependentfiles = src->dependentfiles;
1784 }
1785
1786 #if 0 /* Debugging function */
1787
1788 static char* ffmt(unsigned char *c){
1789         int i;
1790         static char ffmt_str[17];
1791
1792         for (i=0; i<16; i++) {
1793                 if ((c[i] < ' ') || (c[i] > '~'))
1794                         ffmt_str[i]='.';
1795                 else
1796                         ffmt_str[i]=c[i];
1797         }
1798     ffmt_str[16]='\0';
1799         return ffmt_str;
1800 }
1801
1802 #endif
1803
1804 /****************************************************************************
1805 ****************************************************************************/
1806 WERROR move_driver_to_download_area(struct pipes_struct *p,
1807                                     NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1808                                     uint32 level, WERROR *perr)
1809 {
1810         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1811         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1812         const char *architecture;
1813         char *new_dir = NULL;
1814         char *old_name = NULL;
1815         char *new_name = NULL;
1816         connection_struct *conn = NULL;
1817         NTSTATUS nt_status;
1818         SMB_STRUCT_STAT st;
1819         int i;
1820         TALLOC_CTX *ctx = talloc_tos();
1821         int ver = 0;
1822         char *oldcwd;
1823         fstring printdollar;
1824         int printdollar_snum;
1825
1826         *perr = WERR_OK;
1827
1828         if (level==3)
1829                 driver=driver_abstract.info_3;
1830         else if (level==6) {
1831                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1832                 driver = &converted_driver;
1833         } else {
1834                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1835                 return WERR_UNKNOWN_LEVEL;
1836         }
1837
1838         architecture = get_short_archi(driver->environment);
1839         if (!architecture) {
1840                 return WERR_UNKNOWN_PRINTER_DRIVER;
1841         }
1842
1843         fstrcpy(printdollar, "print$");
1844
1845         printdollar_snum = find_service(printdollar);
1846         if (printdollar_snum == -1) {
1847                 *perr = WERR_NO_SUCH_SHARE;
1848                 return WERR_NO_SUCH_SHARE;
1849         }
1850
1851         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1852                                        lp_pathname(printdollar_snum),
1853                                        p->server_info, &oldcwd);
1854         if (!NT_STATUS_IS_OK(nt_status)) {
1855                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1856                          "returned %s\n", nt_errstr(nt_status)));
1857                 *perr = ntstatus_to_werror(nt_status);
1858                 return *perr;
1859         }
1860
1861         DEBUG(5,("Creating first directory\n"));
1862         new_dir = talloc_asprintf(ctx,
1863                                 "%s/%d",
1864                                 architecture,
1865                                 driver->cversion);
1866         if (!new_dir) {
1867                 *perr = WERR_NOMEM;
1868                 goto err_exit;
1869         }
1870         new_dir = driver_unix_convert(conn,new_dir,&st);
1871         if (!new_dir) {
1872                 *perr = WERR_NOMEM;
1873                 goto err_exit;
1874         }
1875
1876         create_directory(conn, NULL, new_dir);
1877
1878         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1879          * listed for this driver which has already been moved, skip it (note:
1880          * drivers may list the same file name several times. Then check if the
1881          * file already exists in archi\cversion\, if so, check that the version
1882          * info (or time stamps if version info is unavailable) is newer (or the
1883          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1884          * Otherwise, delete the file.
1885          *
1886          * If a file is not moved to archi\cversion\ because of an error, all the
1887          * rest of the 'unmoved' driver files are removed from archi\. If one or
1888          * more of the driver's files was already moved to archi\cversion\, it
1889          * potentially leaves the driver in a partially updated state. Version
1890          * trauma will most likely occur if an client attempts to use any printer
1891          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1892          * done is appropriate... later JRR
1893          */
1894
1895         DEBUG(5,("Moving files now !\n"));
1896
1897         if (driver->driverpath && strlen(driver->driverpath)) {
1898                 new_name = talloc_asprintf(ctx,
1899                                         "%s/%s",
1900                                         architecture,
1901                                         driver->driverpath);
1902                 if (!new_name) {
1903                         *perr = WERR_NOMEM;
1904                         goto err_exit;
1905                 }
1906                 old_name = talloc_asprintf(ctx,
1907                                         "%s/%s",
1908                                         new_dir,
1909                                         driver->driverpath);
1910                 if (!old_name) {
1911                         *perr = WERR_NOMEM;
1912                         goto err_exit;
1913                 }
1914
1915                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1916                         new_name = driver_unix_convert(conn,new_name,&st);
1917                         if (!new_name) {
1918                                 *perr = WERR_NOMEM;
1919                                 goto err_exit;
1920                         }
1921                         if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1922                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1923                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1924                                                 new_name, old_name));
1925                                 *perr = WERR_ACCESS_DENIED;
1926                                 ver = -1;
1927                         }
1928                 }
1929         }
1930
1931         if (driver->datafile && strlen(driver->datafile)) {
1932                 if (!strequal(driver->datafile, driver->driverpath)) {
1933                         new_name = talloc_asprintf(ctx,
1934                                         "%s/%s",
1935                                         architecture,
1936                                         driver->datafile);
1937                         if (!new_name) {
1938                                 *perr = WERR_NOMEM;
1939                                 goto err_exit;
1940                         }
1941                         old_name = talloc_asprintf(ctx,
1942                                         "%s/%s",
1943                                         new_dir,
1944                                         driver->datafile);
1945                         if (!old_name) {
1946                                 *perr = WERR_NOMEM;
1947                                 goto err_exit;
1948                         }
1949                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1950                                 new_name = driver_unix_convert(conn,new_name,&st);
1951                                 if (!new_name) {
1952                                         *perr = WERR_NOMEM;
1953                                         goto err_exit;
1954                                 }
1955                                 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1956                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1957                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1958                                                         new_name, old_name));
1959                                         *perr = WERR_ACCESS_DENIED;
1960                                         ver = -1;
1961                                 }
1962                         }
1963                 }
1964         }
1965
1966         if (driver->configfile && strlen(driver->configfile)) {
1967                 if (!strequal(driver->configfile, driver->driverpath) &&
1968                         !strequal(driver->configfile, driver->datafile)) {
1969                         new_name = talloc_asprintf(ctx,
1970                                                 "%s/%s",
1971                                                 architecture,
1972                                                 driver->configfile);
1973                         if (!new_name) {
1974                                 *perr = WERR_NOMEM;
1975                                 goto err_exit;
1976                         }
1977                         old_name = talloc_asprintf(ctx,
1978                                                 "%s/%s",
1979                                                 new_dir,
1980                                                 driver->configfile);
1981                         if (!old_name) {
1982                                 *perr = WERR_NOMEM;
1983                                 goto err_exit;
1984                         }
1985                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1986                                 new_name = driver_unix_convert(conn,new_name,&st);
1987                                 if (!new_name) {
1988                                         *perr = WERR_NOMEM;
1989                                         goto err_exit;
1990                                 }
1991                                 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1992                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1993                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1994                                                         new_name, old_name));
1995                                         *perr = WERR_ACCESS_DENIED;
1996                                         ver = -1;
1997                                 }
1998                         }
1999                 }
2000         }
2001
2002         if (driver->helpfile && strlen(driver->helpfile)) {
2003                 if (!strequal(driver->helpfile, driver->driverpath) &&
2004                         !strequal(driver->helpfile, driver->datafile) &&
2005                         !strequal(driver->helpfile, driver->configfile)) {
2006                         new_name = talloc_asprintf(ctx,
2007                                         "%s/%s",
2008                                         architecture,
2009                                         driver->helpfile);
2010                         if (!new_name) {
2011                                 *perr = WERR_NOMEM;
2012                                 goto err_exit;
2013                         }
2014                         old_name = talloc_asprintf(ctx,
2015                                         "%s/%s",
2016                                         new_dir,
2017                                         driver->helpfile);
2018                         if (!old_name) {
2019                                 *perr = WERR_NOMEM;
2020                                 goto err_exit;
2021                         }
2022                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
2023                                 new_name = driver_unix_convert(conn,new_name,&st);
2024                                 if (!new_name) {
2025                                         *perr = WERR_NOMEM;
2026                                         goto err_exit;
2027                                 }
2028                                 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
2029                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
2030                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
2031                                                         new_name, old_name));
2032                                         *perr = WERR_ACCESS_DENIED;
2033                                         ver = -1;
2034                                 }
2035                         }
2036                 }
2037         }
2038
2039         if (driver->dependentfiles) {
2040                 for (i=0; *driver->dependentfiles[i]; i++) {
2041                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
2042                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
2043                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
2044                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
2045                                 int j;
2046                                 for (j=0; j < i; j++) {
2047                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
2048                                                 goto NextDriver;
2049                                         }
2050                                 }
2051
2052                                 new_name = talloc_asprintf(ctx,
2053                                                 "%s/%s",
2054                                                 architecture,
2055                                                 driver->dependentfiles[i]);
2056                                 if (!new_name) {
2057                                         *perr = WERR_NOMEM;
2058                                         goto err_exit;
2059                                 }
2060                                 old_name = talloc_asprintf(ctx,
2061                                                 "%s/%s",
2062                                                 new_dir,
2063                                                 driver->dependentfiles[i]);
2064                                 if (!old_name) {
2065                                         *perr = WERR_NOMEM;
2066                                         goto err_exit;
2067                                 }
2068                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
2069                                         new_name = driver_unix_convert(conn,new_name,&st);
2070                                         if (!new_name) {
2071                                                 *perr = WERR_NOMEM;
2072                                                 goto err_exit;
2073                                         }
2074                                         if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
2075                                                         OPENX_FILE_EXISTS_TRUNCATE|
2076                                                         OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
2077                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
2078                                                                 new_name, old_name));
2079                                                 *perr = WERR_ACCESS_DENIED;
2080                                                 ver = -1;
2081                                         }
2082                                 }
2083                         }
2084                 NextDriver: ;
2085                 }
2086         }
2087
2088   err_exit:
2089
2090         if (conn != NULL) {
2091                 vfs_ChDir(conn, oldcwd);
2092                 conn_free_internal(conn);
2093         }
2094
2095         if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2096                 return WERR_OK;
2097         }
2098         if (ver == -1) {
2099                 return WERR_UNKNOWN_PRINTER_DRIVER;
2100         }
2101         return (*perr);
2102 }
2103
2104 /****************************************************************************
2105 ****************************************************************************/
2106
2107 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
2108 {
2109         TALLOC_CTX *ctx = talloc_tos();
2110         int len, buflen;
2111         const char *architecture;
2112         char *directory = NULL;
2113         fstring temp_name;
2114         char *key = NULL;
2115         uint8 *buf;
2116         int i, ret;
2117         TDB_DATA dbuf;
2118
2119         architecture = get_short_archi(driver->environment);
2120         if (!architecture) {
2121                 return (uint32)-1;
2122         }
2123
2124         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2125          * \\server is added in the rpc server layer.
2126          * It does make sense to NOT store the server's name in the printer TDB.
2127          */
2128
2129         directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2130                         architecture, driver->cversion);
2131         if (!directory) {
2132                 return (uint32)-1;
2133         }
2134
2135         /* .inf files do not always list a file for each of the four standard files.
2136          * Don't prepend a path to a null filename, or client claims:
2137          *   "The server on which the printer resides does not have a suitable
2138          *   <printer driver name> printer driver installed. Click OK if you
2139          *   wish to install the driver on your local machine."
2140          */
2141         if (strlen(driver->driverpath)) {
2142                 fstrcpy(temp_name, driver->driverpath);
2143                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
2144         }
2145
2146         if (strlen(driver->datafile)) {
2147                 fstrcpy(temp_name, driver->datafile);
2148                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
2149         }
2150
2151         if (strlen(driver->configfile)) {
2152                 fstrcpy(temp_name, driver->configfile);
2153                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
2154         }
2155
2156         if (strlen(driver->helpfile)) {
2157                 fstrcpy(temp_name, driver->helpfile);
2158                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
2159         }
2160
2161         if (driver->dependentfiles) {
2162                 for (i=0; *driver->dependentfiles[i]; i++) {
2163                         fstrcpy(temp_name, driver->dependentfiles[i]);
2164                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
2165                 }
2166         }
2167
2168         key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2169                         architecture, driver->cversion, driver->name);
2170         if (!key) {
2171                 return (uint32)-1;
2172         }
2173
2174         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2175
2176         buf = NULL;
2177         len = buflen = 0;
2178
2179  again:
2180         len = 0;
2181         len += tdb_pack(buf+len, buflen-len, "dffffffff",
2182                         driver->cversion,
2183                         driver->name,
2184                         driver->environment,
2185                         driver->driverpath,
2186                         driver->datafile,
2187                         driver->configfile,
2188                         driver->helpfile,
2189                         driver->monitorname,
2190                         driver->defaultdatatype);
2191
2192         if (driver->dependentfiles) {
2193                 for (i=0; *driver->dependentfiles[i]; i++) {
2194                         len += tdb_pack(buf+len, buflen-len, "f",
2195                                         driver->dependentfiles[i]);
2196                 }
2197         }
2198
2199         if (len != buflen) {
2200                 buf = (uint8 *)SMB_REALLOC(buf, len);
2201                 if (!buf) {
2202                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2203                         ret = -1;
2204                         goto done;
2205                 }
2206                 buflen = len;
2207                 goto again;
2208         }
2209
2210         dbuf.dptr = buf;
2211         dbuf.dsize = len;
2212
2213         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2214
2215 done:
2216         if (ret)
2217                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2218
2219         SAFE_FREE(buf);
2220         return ret;
2221 }
2222
2223 /****************************************************************************
2224 ****************************************************************************/
2225 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2226 {
2227         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2228
2229         ZERO_STRUCT(info3);
2230         info3.cversion = driver->version;
2231         fstrcpy(info3.name,driver->name);
2232         fstrcpy(info3.environment,driver->environment);
2233         fstrcpy(info3.driverpath,driver->driverpath);
2234         fstrcpy(info3.datafile,driver->datafile);
2235         fstrcpy(info3.configfile,driver->configfile);
2236         fstrcpy(info3.helpfile,driver->helpfile);
2237         fstrcpy(info3.monitorname,driver->monitorname);
2238         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2239         info3.dependentfiles = driver->dependentfiles;
2240
2241         return add_a_printer_driver_3(&info3);
2242 }
2243
2244
2245 /****************************************************************************
2246 ****************************************************************************/
2247 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2248 {
2249         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2250
2251         ZERO_STRUCT(info);
2252
2253         fstrcpy(info.name, driver);
2254         fstrcpy(info.defaultdatatype, "RAW");
2255
2256         fstrcpy(info.driverpath, "");
2257         fstrcpy(info.datafile, "");
2258         fstrcpy(info.configfile, "");
2259         fstrcpy(info.helpfile, "");
2260
2261         if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2262                 return WERR_NOMEM;
2263
2264         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2265         fstrcpy(info.dependentfiles[0], "");
2266
2267         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2268         if (!*info_ptr) {
2269                 SAFE_FREE(info.dependentfiles);
2270                 return WERR_NOMEM;
2271         }
2272
2273         return WERR_OK;
2274 }
2275
2276 /****************************************************************************
2277 ****************************************************************************/
2278 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
2279                                      const char *drivername, const char *arch,
2280                                      uint32_t version)
2281 {
2282         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2283         TDB_DATA dbuf;
2284         const char *architecture;
2285         int len = 0;
2286         int i;
2287         char *key = NULL;
2288
2289         ZERO_STRUCT(driver);
2290
2291         architecture = get_short_archi(arch);
2292         if ( !architecture ) {
2293                 return WERR_UNKNOWN_PRINTER_DRIVER;
2294         }
2295
2296         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2297
2298         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2299                 version = 0;
2300
2301         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2302
2303         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2304                                 architecture, version, drivername) < 0) {
2305                 return WERR_NOMEM;
2306         }
2307
2308         dbuf = tdb_fetch_bystring(tdb_drivers, key);
2309         if (!dbuf.dptr) {
2310                 SAFE_FREE(key);
2311                 return WERR_UNKNOWN_PRINTER_DRIVER;
2312         }
2313
2314         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2315                           &driver.cversion,
2316                           driver.name,
2317                           driver.environment,
2318                           driver.driverpath,
2319                           driver.datafile,
2320                           driver.configfile,
2321                           driver.helpfile,
2322                           driver.monitorname,
2323                           driver.defaultdatatype);
2324
2325         i=0;
2326         while (len < dbuf.dsize) {
2327                 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2328                 if ( !driver.dependentfiles ) {
2329                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2330                         break;
2331                 }
2332
2333                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2334                                   &driver.dependentfiles[i]);
2335                 i++;
2336         }
2337
2338         if ( driver.dependentfiles )
2339                 fstrcpy( driver.dependentfiles[i], "" );
2340
2341         SAFE_FREE(dbuf.dptr);
2342         SAFE_FREE(key);
2343
2344         if (len != dbuf.dsize) {
2345                 SAFE_FREE(driver.dependentfiles);
2346
2347                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2348         }
2349
2350         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2351         if (!*info_ptr) {
2352                 SAFE_FREE(driver.dependentfiles);
2353                 return WERR_NOMEM;
2354         }
2355
2356         return WERR_OK;
2357 }
2358
2359 /****************************************************************************
2360  Debugging function, dump at level 6 the struct in the logs.
2361 ****************************************************************************/
2362
2363 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2364 {
2365         uint32 result;
2366         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2367         int i;
2368
2369         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2370
2371         switch (level)
2372         {
2373                 case 3:
2374                 {
2375                         if (driver.info_3 == NULL)
2376                                 result=5;
2377                         else {
2378                                 info3=driver.info_3;
2379
2380                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
2381                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
2382                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
2383                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
2384                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
2385                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
2386                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
2387                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
2388                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2389
2390                                 for (i=0; info3->dependentfiles &&
2391                                           *info3->dependentfiles[i]; i++) {
2392                                         DEBUGADD(20,("dependentfile:[%s]\n",
2393                                                       info3->dependentfiles[i]));
2394                                 }
2395                                 result=0;
2396                         }
2397                         break;
2398                 }
2399                 default:
2400                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2401                         result=1;
2402                         break;
2403         }
2404
2405         return result;
2406 }
2407
2408 /****************************************************************************
2409 ****************************************************************************/
2410 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2411 {
2412         int len = 0;
2413
2414         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2415
2416         if (!nt_devmode)
2417                 return len;
2418
2419         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2420                         nt_devmode->devicename,
2421                         nt_devmode->formname,
2422
2423                         nt_devmode->specversion,
2424                         nt_devmode->driverversion,
2425                         nt_devmode->size,
2426                         nt_devmode->driverextra,
2427                         nt_devmode->orientation,
2428                         nt_devmode->papersize,
2429                         nt_devmode->paperlength,
2430                         nt_devmode->paperwidth,
2431                         nt_devmode->scale,
2432                         nt_devmode->copies,
2433                         nt_devmode->defaultsource,
2434                         nt_devmode->printquality,
2435                         nt_devmode->color,
2436                         nt_devmode->duplex,
2437                         nt_devmode->yresolution,
2438                         nt_devmode->ttoption,
2439                         nt_devmode->collate,
2440                         nt_devmode->logpixels,
2441
2442                         nt_devmode->fields,
2443                         nt_devmode->bitsperpel,
2444                         nt_devmode->pelswidth,
2445                         nt_devmode->pelsheight,
2446                         nt_devmode->displayflags,
2447                         nt_devmode->displayfrequency,
2448                         nt_devmode->icmmethod,
2449                         nt_devmode->icmintent,
2450                         nt_devmode->mediatype,
2451                         nt_devmode->dithertype,
2452                         nt_devmode->reserved1,
2453                         nt_devmode->reserved2,
2454                         nt_devmode->panningwidth,
2455                         nt_devmode->panningheight,
2456                         nt_devmode->nt_dev_private);
2457
2458         if (nt_devmode->nt_dev_private) {
2459                 len += tdb_pack(buf+len, buflen-len, "B",
2460                                 nt_devmode->driverextra,
2461                                 nt_devmode->nt_dev_private);
2462         }
2463
2464         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2465
2466         return len;
2467 }
2468
2469 /****************************************************************************
2470  Pack all values in all printer keys
2471  ***************************************************************************/
2472
2473 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2474 {
2475         int             len = 0;
2476         int             i, j;
2477         REGISTRY_VALUE  *val;
2478         REGVAL_CTR      *val_ctr;
2479         char *path = NULL;
2480         int             num_values;
2481
2482         if ( !data )
2483                 return 0;
2484
2485         /* loop over all keys */
2486
2487         for ( i=0; i<data->num_keys; i++ ) {
2488                 val_ctr = data->keys[i].values;
2489                 num_values = regval_ctr_numvals( val_ctr );
2490
2491                 /* pack the keyname followed by a empty value */
2492
2493                 len += tdb_pack(buf+len, buflen-len, "pPdB",
2494                                 &data->keys[i].name,
2495                                 data->keys[i].name,
2496                                 REG_NONE,
2497                                 0,
2498                                 NULL);
2499
2500                 /* now loop over all values */
2501
2502                 for ( j=0; j<num_values; j++ ) {
2503                         /* pathname should be stored as <key>\<value> */
2504
2505                         val = regval_ctr_specific_value( val_ctr, j );
2506                         if (asprintf(&path, "%s\\%s",
2507                                         data->keys[i].name,
2508                                         regval_name(val)) < 0) {
2509                                 return -1;
2510                         }
2511
2512                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2513                                         val,
2514                                         path,
2515                                         regval_type(val),
2516                                         regval_size(val),
2517                                         regval_data_p(val) );
2518
2519                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2520                         SAFE_FREE(path);
2521                 }
2522
2523         }
2524
2525         /* terminator */
2526
2527         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2528
2529         return len;
2530 }
2531
2532
2533 /****************************************************************************
2534  Delete a printer - this just deletes the printer info file, any open
2535  handles are not affected.
2536 ****************************************************************************/
2537
2538 uint32 del_a_printer(const char *sharename)
2539 {
2540         TDB_DATA kbuf;
2541         char *printdb_path = NULL;
2542         TALLOC_CTX *ctx = talloc_tos();
2543
2544         kbuf = make_printer_tdbkey(ctx, sharename);
2545         tdb_delete(tdb_printers, kbuf);
2546
2547         kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2548         tdb_delete(tdb_printers, kbuf);
2549
2550         close_all_print_db();
2551
2552         if (geteuid() == 0) {
2553                 if (asprintf(&printdb_path, "%s%s.tdb",
2554                                 cache_path("printing/"),
2555                                 sharename) < 0) {
2556                         return (uint32)-1;
2557                 }
2558                 unlink(printdb_path);
2559                 SAFE_FREE(printdb_path);
2560         }
2561
2562         return 0;
2563 }
2564
2565 /****************************************************************************
2566 ****************************************************************************/
2567 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2568 {
2569         uint8 *buf;
2570         int buflen, len;
2571         int retlen;
2572         WERROR ret;
2573         TDB_DATA kbuf, dbuf;
2574
2575         /*
2576          * in addprinter: no servername and the printer is the name
2577          * in setprinter: servername is \\server
2578          *                and printer is \\server\\printer
2579          *
2580          * Samba manages only local printers.
2581          * we currently don't support things like i
2582          * path=\\other_server\printer
2583          *
2584          * We only store the printername, not \\server\printername
2585          */
2586
2587         if ( info->servername[0] != '\0' ) {
2588                 trim_string(info->printername, info->servername, NULL);
2589                 trim_char(info->printername, '\\', '\0');
2590                 info->servername[0]='\0';
2591         }
2592
2593         /*
2594          * JFM: one day I'll forget.
2595          * below that's info->portname because that's the SAMBA sharename
2596          * and I made NT 'thinks' it's the portname
2597          * the info->sharename is the thing you can name when you add a printer
2598          * that's the short-name when you create shared printer for 95/98
2599          * So I've made a limitation in SAMBA: you can only have 1 printer model
2600          * behind a SAMBA share.
2601          */
2602
2603         buf = NULL;
2604         buflen = 0;
2605
2606  again:
2607         len = 0;
2608         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2609                         info->attributes,
2610                         info->priority,
2611                         info->default_priority,
2612                         info->starttime,
2613                         info->untiltime,
2614                         info->status,
2615                         info->cjobs,
2616                         info->averageppm,
2617                         info->changeid,
2618                         info->c_setprinter,
2619                         info->setuptime,
2620                         info->servername,
2621                         info->printername,
2622                         info->sharename,
2623                         info->portname,
2624                         info->drivername,
2625                         info->comment,
2626                         info->location,
2627                         info->sepfile,
2628                         info->printprocessor,
2629                         info->datatype,
2630                         info->parameters);
2631
2632         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2633         retlen = pack_values( info->data, buf+len, buflen-len );
2634         if (retlen == -1) {
2635                 ret = WERR_NOMEM;
2636                 goto done;
2637         }
2638         len += retlen;
2639
2640         if (buflen != len) {
2641                 buf = (uint8 *)SMB_REALLOC(buf, len);
2642                 if (!buf) {
2643                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2644                         ret = WERR_NOMEM;
2645                         goto done;
2646                 }
2647                 buflen = len;
2648                 goto again;
2649         }
2650
2651         kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2652
2653         dbuf.dptr = buf;
2654         dbuf.dsize = len;
2655
2656         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2657
2658 done:
2659         if (!W_ERROR_IS_OK(ret))
2660                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2661
2662         SAFE_FREE(buf);
2663
2664         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2665                  info->sharename, info->drivername, info->portname, len));
2666
2667         return ret;
2668 }
2669
2670
2671 /****************************************************************************
2672  Malloc and return an NT devicemode.
2673 ****************************************************************************/
2674
2675 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2676 {
2677
2678         char adevice[MAXDEVICENAME];
2679         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2680
2681         if (nt_devmode == NULL) {
2682                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2683                 return NULL;
2684         }
2685
2686         ZERO_STRUCTP(nt_devmode);
2687
2688         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2689         fstrcpy(nt_devmode->devicename, adevice);
2690
2691         fstrcpy(nt_devmode->formname, "Letter");
2692
2693         nt_devmode->specversion      = 0x0401;
2694         nt_devmode->driverversion    = 0x0400;
2695         nt_devmode->size             = 0x00DC;
2696         nt_devmode->driverextra      = 0x0000;
2697         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2698                                        DEFAULTSOURCE | COPIES | SCALE |
2699                                        PAPERSIZE | ORIENTATION;
2700         nt_devmode->orientation      = 1;
2701         nt_devmode->papersize        = PAPER_LETTER;
2702         nt_devmode->paperlength      = 0;
2703         nt_devmode->paperwidth       = 0;
2704         nt_devmode->scale            = 0x64;
2705         nt_devmode->copies           = 1;
2706         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2707         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2708         nt_devmode->color            = COLOR_MONOCHROME;
2709         nt_devmode->duplex           = DUP_SIMPLEX;
2710         nt_devmode->yresolution      = 0;
2711         nt_devmode->ttoption         = TT_SUBDEV;
2712         nt_devmode->collate          = COLLATE_FALSE;
2713         nt_devmode->icmmethod        = 0;
2714         nt_devmode->icmintent        = 0;
2715         nt_devmode->mediatype        = 0;
2716         nt_devmode->dithertype       = 0;
2717
2718         /* non utilisés par un driver d'imprimante */
2719         nt_devmode->logpixels        = 0;
2720         nt_devmode->bitsperpel       = 0;
2721         nt_devmode->pelswidth        = 0;
2722         nt_devmode->pelsheight       = 0;
2723         nt_devmode->displayflags     = 0;
2724         nt_devmode->displayfrequency = 0;
2725         nt_devmode->reserved1        = 0;
2726         nt_devmode->reserved2        = 0;
2727         nt_devmode->panningwidth     = 0;
2728         nt_devmode->panningheight    = 0;
2729
2730         nt_devmode->nt_dev_private = NULL;
2731         return nt_devmode;
2732 }
2733
2734 /****************************************************************************
2735  Deepcopy an NT devicemode.
2736 ****************************************************************************/
2737
2738 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2739 {
2740         NT_DEVICEMODE *new_nt_devicemode = NULL;
2741
2742         if ( !nt_devicemode )
2743                 return NULL;
2744
2745         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2746                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2747                 return NULL;
2748         }
2749
2750         new_nt_devicemode->nt_dev_private = NULL;
2751         if (nt_devicemode->nt_dev_private != NULL) {
2752                 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2753                         SAFE_FREE(new_nt_devicemode);
2754                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2755                         return NULL;
2756         }
2757         }
2758
2759         return new_nt_devicemode;
2760 }
2761
2762 /****************************************************************************
2763  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2764 ****************************************************************************/
2765
2766 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2767 {
2768         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2769
2770         if(nt_devmode == NULL)
2771                 return;
2772
2773         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2774
2775         SAFE_FREE(nt_devmode->nt_dev_private);
2776         SAFE_FREE(*devmode_ptr);
2777 }
2778
2779 /****************************************************************************
2780  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2781 ****************************************************************************/
2782
2783 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2784 {
2785         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2786
2787         if ( !info )
2788                 return;
2789
2790         free_nt_devicemode(&info->devmode);
2791
2792         TALLOC_FREE( *info_ptr );
2793 }
2794
2795
2796 /****************************************************************************
2797 ****************************************************************************/
2798 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2799 {
2800         int len = 0;
2801         int extra_len = 0;
2802         NT_DEVICEMODE devmode;
2803
2804         ZERO_STRUCT(devmode);
2805
2806         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2807
2808         if (!*nt_devmode) return len;
2809
2810         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2811                           devmode.devicename,
2812                           devmode.formname,
2813
2814                           &devmode.specversion,
2815                           &devmode.driverversion,
2816                           &devmode.size,
2817                           &devmode.driverextra,
2818                           &devmode.orientation,
2819                           &devmode.papersize,
2820                           &devmode.paperlength,
2821                           &devmode.paperwidth,
2822                           &devmode.scale,
2823                           &devmode.copies,
2824                           &devmode.defaultsource,
2825                           &devmode.printquality,
2826                           &devmode.color,
2827                           &devmode.duplex,
2828                           &devmode.yresolution,
2829                           &devmode.ttoption,
2830                           &devmode.collate,
2831                           &devmode.logpixels,
2832
2833                           &devmode.fields,
2834                           &devmode.bitsperpel,
2835                           &devmode.pelswidth,
2836                           &devmode.pelsheight,
2837                           &devmode.displayflags,
2838                           &devmode.displayfrequency,
2839                           &devmode.icmmethod,
2840                           &devmode.icmintent,
2841                           &devmode.mediatype,
2842                           &devmode.dithertype,
2843                           &devmode.reserved1,
2844                           &devmode.reserved2,
2845                           &devmode.panningwidth,
2846                           &devmode.panningheight,
2847                           &devmode.nt_dev_private);
2848
2849         if (devmode.nt_dev_private) {
2850                 /* the len in tdb_unpack is an int value and
2851                  * devmode.driverextra is only a short
2852                  */
2853                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2854                 devmode.driverextra=(uint16)extra_len;
2855
2856                 /* check to catch an invalid TDB entry so we don't segfault */
2857                 if (devmode.driverextra == 0) {
2858                         devmode.nt_dev_private = NULL;
2859                 }
2860         }
2861
2862         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2863         if (!*nt_devmode) {
2864                 SAFE_FREE(devmode.nt_dev_private);
2865                 return -1;
2866         }
2867
2868         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2869         if (devmode.nt_dev_private)
2870                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2871
2872         return len;
2873 }
2874
2875 /****************************************************************************
2876  Allocate and initialize a new slot.
2877 ***************************************************************************/
2878
2879 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2880 {
2881         NT_PRINTER_KEY  *d;
2882         int             key_index;
2883
2884         if ( !name || !data )
2885                 return -1;
2886
2887         /* allocate another slot in the NT_PRINTER_KEY array */
2888
2889         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2890                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2891                 return -1;
2892         }
2893
2894         data->keys = d;
2895
2896         key_index = data->num_keys;
2897
2898         /* initialze new key */
2899
2900         data->keys[key_index].name = talloc_strdup( data, name );
2901
2902         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2903                 return -1;
2904
2905         data->num_keys++;
2906
2907         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2908
2909         return key_index;
2910 }
2911
2912 /****************************************************************************
2913  search for a registry key name in the existing printer data
2914  ***************************************************************************/
2915
2916 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2917 {
2918         int i;
2919
2920         for ( i=0; i<data->num_keys; i++ ) {
2921                 if ( strequal( data->keys[i].name, name ) ) {
2922
2923                         /* cleanup memory */
2924
2925                         TALLOC_FREE( data->keys[i].name );
2926                         TALLOC_FREE( data->keys[i].values );
2927
2928                         /* if not the end of the array, move remaining elements down one slot */
2929
2930                         data->num_keys--;
2931                         if ( data->num_keys && (i < data->num_keys) )
2932                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2933
2934                         break;
2935                 }
2936         }
2937
2938
2939         return data->num_keys;
2940 }
2941
2942 /****************************************************************************
2943  search for a registry key name in the existing printer data
2944  ***************************************************************************/
2945
2946 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2947 {
2948         int             key_index = -1;
2949         int             i;
2950
2951         if ( !data || !name )
2952                 return -1;
2953
2954         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2955
2956         /* loop over all existing keys */
2957
2958         for ( i=0; i<data->num_keys; i++ ) {
2959                 if ( strequal(data->keys[i].name, name) ) {
2960                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2961                         key_index = i;
2962                         break;
2963
2964                 }
2965         }
2966
2967         return key_index;
2968 }
2969
2970 /****************************************************************************
2971  ***************************************************************************/
2972
2973 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2974 {
2975         int     i, j;
2976         int     key_len;
2977         int     num_subkeys = 0;
2978         char    *p;
2979         fstring *subkeys_ptr = NULL;
2980         fstring subkeyname;
2981
2982         *subkeys = NULL;
2983
2984         if ( !data )
2985                 return 0;
2986
2987         if ( !key )
2988                 return -1;
2989
2990         /* special case of asking for the top level printer data registry key names */
2991
2992         if ( strlen(key) == 0 ) {
2993                 for ( i=0; i<data->num_keys; i++ ) {
2994
2995                         /* found a match, so allocate space and copy the name */
2996
2997                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2998                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2999                                         num_subkeys+1));
3000                                 return -1;
3001                         }
3002
3003                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3004                         num_subkeys++;
3005                 }
3006
3007                 goto done;
3008         }
3009
3010         /* asking for the subkeys of some key */
3011         /* subkey paths are stored in the key name using '\' as the delimiter */
3012
3013         for ( i=0; i<data->num_keys; i++ ) {
3014                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3015
3016                         /* if we found the exact key, then break */
3017                         key_len = strlen( key );
3018                         if ( strlen(data->keys[i].name) == key_len )
3019                                 break;
3020
3021                         /* get subkey path */
3022
3023                         p = data->keys[i].name + key_len;
3024                         if ( *p == '\\' )
3025                                 p++;
3026                         fstrcpy( subkeyname, p );
3027                         if ( (p = strchr( subkeyname, '\\' )) )
3028                                 *p = '\0';
3029
3030                         /* don't add a key more than once */
3031
3032                         for ( j=0; j<num_subkeys; j++ ) {
3033                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
3034                                         break;
3035                         }
3036
3037                         if ( j != num_subkeys )
3038                                 continue;
3039
3040                         /* found a match, so allocate space and copy the name */
3041
3042                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3043                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3044                                         num_subkeys+1));
3045                                 return 0;
3046                         }
3047
3048                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3049                         num_subkeys++;
3050                 }
3051
3052         }
3053
3054         /* return error if the key was not found */
3055
3056         if ( i == data->num_keys ) {
3057                 SAFE_FREE(subkeys_ptr);
3058                 return -1;
3059         }
3060
3061 done:
3062         /* tag off the end */
3063
3064         if (num_subkeys)
3065                 fstrcpy(subkeys_ptr[num_subkeys], "" );
3066
3067         *subkeys = subkeys_ptr;
3068
3069         return num_subkeys;
3070 }
3071
3072 #ifdef HAVE_ADS
3073 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3074                             const char *sz)
3075 {
3076         smb_ucs2_t conv_str[1024];
3077         size_t str_size;
3078
3079         regval_ctr_delvalue(ctr, val_name);
3080         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
3081                              STR_TERMINATE | STR_NOALIGN);
3082         regval_ctr_addvalue(ctr, val_name, REG_SZ,
3083                             (char *) conv_str, str_size);
3084 }
3085
3086 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3087                                uint32 dword)
3088 {
3089         regval_ctr_delvalue(ctr, val_name);
3090         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3091                             (char *) &dword, sizeof(dword));
3092 }
3093
3094 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3095                               bool b)
3096 {
3097         uint8 bin_bool = (b ? 1 : 0);
3098         regval_ctr_delvalue(ctr, val_name);
3099         regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3100                             (char *) &bin_bool, sizeof(bin_bool));
3101 }
3102
3103 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3104                                          const char *multi_sz)
3105 {
3106         smb_ucs2_t *conv_strs = NULL;
3107         size_t str_size;
3108
3109         /* a multi-sz has to have a null string terminator, i.e., the last
3110            string must be followed by two nulls */
3111         str_size = strlen(multi_sz) + 2;
3112         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
3113         if (!conv_strs) {
3114                 return;
3115         }
3116
3117         /* Change to byte units. */
3118         str_size *= sizeof(smb_ucs2_t);
3119         push_ucs2(NULL, conv_strs, multi_sz, str_size,
3120                   STR_TERMINATE | STR_NOALIGN);
3121
3122         regval_ctr_delvalue(ctr, val_name);
3123         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
3124                             (char *) conv_strs, str_size);
3125         SAFE_FREE(conv_strs);
3126 }
3127
3128 /****************************************************************************
3129  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3130  *
3131  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3132  * @return bool indicating success or failure
3133  ***************************************************************************/
3134
3135 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3136 {
3137         REGVAL_CTR *ctr = NULL;
3138         fstring longname;
3139         const char *dnssuffix;
3140         char *allocated_string = NULL;
3141         const char *ascii_str;
3142         int i;
3143
3144         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3145                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3146         ctr = info2->data->keys[i].values;
3147
3148         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3149         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3150
3151         /* we make the assumption that the netbios name is the same
3152            as the DNS name sinc ethe former will be what we used to
3153            join the domain */
3154
3155         dnssuffix = get_mydnsdomname(talloc_tos());
3156         if (dnssuffix && *dnssuffix) {
3157                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3158         } else {
3159                 fstrcpy( longname, global_myname() );
3160         }
3161
3162         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3163
3164         if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3165                 return false;
3166         }
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, GUID_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         int ret;
3247
3248         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3249
3250         /* figure out where to publish */
3251         ads_find_machine_acct(ads, &res, global_myname());
3252
3253         /* We use ldap_get_dn here as we need the answer
3254          * in utf8 to call ldap_explode_dn(). JRA. */
3255
3256         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3257         if (!srv_dn_utf8) {
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                 return WERR_SERVER_UNAVAILABLE;
3265         }
3266         /* Now convert to CH_UNIX. */
3267         if (!pull_utf8_allocate(&srv_dn, srv_dn_utf8, &converted_size)) {
3268                 ldap_memfree(srv_dn_utf8);
3269                 ldap_memfree(srv_cn_utf8);
3270                 return WERR_SERVER_UNAVAILABLE;
3271         }
3272         if (!pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3273                 ldap_memfree(srv_dn_utf8);
3274                 ldap_memfree(srv_cn_utf8);
3275                 SAFE_FREE(srv_dn);
3276                 return WERR_SERVER_UNAVAILABLE;
3277         }
3278
3279         ldap_memfree(srv_dn_utf8);
3280         ldap_memfree(srv_cn_utf8);
3281
3282         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3283         if (!srv_cn_escaped) {
3284                 SAFE_FREE(srv_cn_0);
3285                 SAFE_FREE(srv_dn);
3286                 return WERR_SERVER_UNAVAILABLE;
3287         }
3288         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3289         if (!sharename_escaped) {
3290                 SAFE_FREE(srv_cn_escaped);
3291                 SAFE_FREE(srv_cn_0);
3292                 SAFE_FREE(srv_dn);
3293                 return WERR_SERVER_UNAVAILABLE;
3294         }
3295
3296         ret = asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3297
3298         SAFE_FREE(srv_dn);
3299         SAFE_FREE(srv_cn_0);
3300         SAFE_FREE(srv_cn_escaped);
3301         SAFE_FREE(sharename_escaped);
3302
3303         if (ret == -1) {
3304                 return WERR_NOMEM;
3305         }
3306
3307         /* build the ads mods */
3308         ctx = talloc_init("nt_printer_publish_ads");
3309         if (ctx == NULL) {
3310                 SAFE_FREE(prt_dn);
3311                 return WERR_NOMEM;
3312         }
3313
3314         mods = ads_init_mods(ctx);
3315
3316         if (mods == NULL) {
3317                 SAFE_FREE(prt_dn);
3318                 talloc_destroy(ctx);
3319                 return WERR_NOMEM;
3320         }
3321
3322         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3323         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3324                     printer->info_2->sharename);
3325
3326         /* publish it */
3327         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3328         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3329                 int i;
3330                 for (i=0; mods[i] != 0; i++)
3331                         ;
3332                 mods[i] = (LDAPMod *)-1;
3333                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3334         }
3335
3336         if (!ADS_ERR_OK(ads_rc))
3337                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3338
3339         talloc_destroy(ctx);
3340
3341         /* retreive the guid and store it locally */
3342         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3343                 ZERO_STRUCT(guid);
3344                 ads_pull_guid(ads, res, &guid);
3345                 ads_msgfree(ads, res);
3346                 store_printer_guid(printer->info_2, guid);
3347                 win_rc = mod_a_printer(printer, 2);
3348         }
3349
3350         SAFE_FREE(prt_dn);
3351         return win_rc;
3352 }
3353
3354 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3355                                        NT_PRINTER_INFO_LEVEL *printer)
3356 {
3357         ADS_STATUS ads_rc;
3358         LDAPMessage *res = NULL;
3359         char *prt_dn = NULL;
3360
3361         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3362
3363         /* remove the printer from the directory */
3364         ads_rc = ads_find_printer_on_server(ads, &res,
3365                             printer->info_2->sharename, global_myname());
3366
3367         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3368                 prt_dn = ads_get_dn(ads, res);
3369                 if (!prt_dn) {
3370                         ads_msgfree(ads, res);
3371                         return WERR_NOMEM;
3372                 }
3373                 ads_rc = ads_del_dn(ads, prt_dn);
3374                 ads_memfree(ads, prt_dn);
3375         }
3376
3377         if (res) {
3378                 ads_msgfree(ads, res);
3379         }
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 DSPRINT_PUBLISH:
3403         case DSPRINT_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 DSPRINT_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 DSPRINT_PUBLISH:
3447         case DSPRINT_UPDATE:
3448                 win_rc = nt_printer_publish_ads(ads, printer);
3449                 break;
3450         case DSPRINT_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 = NT_STATUS_IS_OK(GUID_from_string( 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                                       GUID_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,NULL);
3929         if (numlines == 0 || lines == NULL) {
3930                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3931                 TALLOC_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                         TALLOC_FREE(lines);
3976                         return;
3977                 }
3978         }
3979
3980         TALLOC_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(const 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 *mem_ctx, NT_DEVICEMODE *nt_devmode,
4568                                 const uint8_t *data, uint32_t data_len)
4569 {
4570         struct spoolss_DeviceMode devmode;
4571         enum ndr_err_code ndr_err;
4572         DATA_BLOB blob;
4573
4574         ZERO_STRUCT(devmode);
4575
4576         blob = data_blob_const(data, data_len);
4577
4578         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
4579                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4580         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4581                 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4582                 return false;
4583         }
4584
4585         return convert_devicemode("", &devmode, &nt_devmode);
4586 }
4587
4588 /****************************************************************************
4589  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4590
4591  1. Use the driver's config DLL to this UNC printername and:
4592     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4593     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4594  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4595
4596  The last step triggers saving the "driver initialization" information for
4597  this printer into the tdb. Later, new printers that use this driver will
4598  have this initialization information bound to them. This simulates the
4599  driver initialization, as if it had run on the Samba server (as it would
4600  have done on NT).
4601
4602  The Win32 client side code requirement sucks! But until we can run arbitrary
4603  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4604
4605  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4606  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4607  about it and you will realize why.  JRR 010720
4608 ****************************************************************************/
4609
4610 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4611 {
4612         WERROR        status       = WERR_OK;
4613         TALLOC_CTX    *ctx         = NULL;
4614         NT_DEVICEMODE *nt_devmode  = NULL;
4615         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4616
4617         /*
4618          * When the DEVMODE is already set on the printer, don't try to unpack it.
4619          */
4620         DEBUG(8,("save_driver_init_2: Enter...\n"));
4621
4622         if ( !printer->info_2->devmode && data_len ) {
4623                 /*
4624                  * Set devmode on printer info, so entire printer initialization can be
4625                  * saved to tdb.
4626                  */
4627
4628                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4629                         return WERR_NOMEM;
4630
4631                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4632                         status = WERR_NOMEM;
4633                         goto done;
4634                 }
4635
4636                 ZERO_STRUCTP(nt_devmode);
4637
4638                 /*
4639                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4640                  * Convert it to to a devmode structure
4641                  */
4642                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4643                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4644                         status = WERR_INVALID_PARAM;
4645                         goto done;
4646                 }
4647
4648                 printer->info_2->devmode = nt_devmode;
4649         }
4650
4651         /*
4652          * Pack up and add (or update) the DEVMODE and any current printer data to
4653          * a 'driver init' element in the tdb
4654          *
4655          */
4656
4657         if ( update_driver_init(printer, 2) != 0 ) {
4658                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4659                 status = WERR_NOMEM;
4660                 goto done;
4661         }
4662
4663         /*
4664          * If driver initialization info was successfully saved, set the current
4665          * printer to match it. This allows initialization of the current printer
4666          * as well as the driver.
4667          */
4668         status = mod_a_printer(printer, 2);
4669         if (!W_ERROR_IS_OK(status)) {
4670                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4671                                   printer->info_2->printername));
4672         }
4673
4674   done:
4675         talloc_destroy(ctx);
4676         free_nt_devicemode( &nt_devmode );
4677
4678         printer->info_2->devmode = tmp_devmode;
4679
4680         return status;
4681 }
4682
4683 /****************************************************************************
4684  Update the driver init info (DEVMODE and specifics) for a printer
4685 ****************************************************************************/
4686
4687 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4688 {
4689         WERROR status = WERR_OK;
4690
4691         switch (level) {
4692                 case 2:
4693                         status = save_driver_init_2( printer, data, data_len );
4694                         break;
4695                 default:
4696                         status = WERR_UNKNOWN_LEVEL;
4697                         break;
4698         }
4699
4700         return status;
4701 }
4702
4703 /****************************************************************************
4704  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4705
4706  Previously the code had a memory allocation problem because it always
4707  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4708  as a long as the original handle is open.  So if the client made a lot
4709  of getprinter[data]() calls, the memory usage would climb.  Now we use
4710  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4711  still use the Printer_entry->ctx for maintaining the cache copy though
4712  since that object must live as long as the handle by definition.
4713                                                     --jerry
4714
4715 ****************************************************************************/
4716
4717 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4718                         const char *sharename, bool get_loc_com)
4719 {
4720         WERROR result;
4721         fstring servername;
4722
4723         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4724
4725         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4726                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4727                 return WERR_NOMEM;
4728         }
4729
4730         switch (level) {
4731                 case 2:
4732                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4733                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4734                                 TALLOC_FREE( *pp_printer );
4735                                 return WERR_NOMEM;
4736                         }
4737
4738                         if ( print_hnd )
4739                                 fstrcpy( servername, print_hnd->servername );
4740                         else {
4741                                 fstrcpy( servername, "%L" );
4742                                 standard_sub_basic( "", "", servername,
4743                                                     sizeof(servername)-1 );
4744                         }
4745
4746                         result = get_a_printer_2( (*pp_printer)->info_2,
4747                                         servername, sharename, get_loc_com);
4748
4749                         /* we have a new printer now.  Save it with this handle */
4750
4751                         if ( !W_ERROR_IS_OK(result) ) {
4752                                 TALLOC_FREE( *pp_printer );
4753                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4754                                         sharename, (unsigned int)level, win_errstr(result)));
4755                                 return result;
4756                         }
4757
4758                         dump_a_printer( *pp_printer, level);
4759
4760                         break;
4761
4762                 default:
4763                         TALLOC_FREE( *pp_printer );
4764                         return WERR_UNKNOWN_LEVEL;
4765         }
4766
4767         return WERR_OK;
4768 }
4769
4770 WERROR get_a_printer( Printer_entry *print_hnd,
4771                         NT_PRINTER_INFO_LEVEL **pp_printer,
4772                         uint32 level,
4773                         const char *sharename)
4774 {
4775         return get_a_printer_internal(print_hnd, pp_printer, level,
4776                                         sharename, true);
4777 }
4778
4779 WERROR get_a_printer_search( Printer_entry *print_hnd,
4780                         NT_PRINTER_INFO_LEVEL **pp_printer,
4781                         uint32 level,
4782                         const char *sharename)
4783 {
4784         return get_a_printer_internal(print_hnd, pp_printer, level,
4785                                         sharename, false);
4786 }
4787
4788 /****************************************************************************
4789  Deletes a NT_PRINTER_INFO_LEVEL struct.
4790 ****************************************************************************/
4791
4792 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4793 {
4794         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4795
4796         if ( !printer )
4797                 return 0;
4798
4799         switch (level) {
4800                 case 2:
4801                         if ( printer->info_2 )
4802                                 free_nt_printer_info_level_2(&printer->info_2);
4803                         break;
4804
4805                 default:
4806                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4807                         return 1;
4808         }
4809
4810         TALLOC_FREE(*pp_printer);
4811
4812         return 0;
4813 }
4814
4815 /****************************************************************************
4816 ****************************************************************************/
4817 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4818 {
4819         uint32 result;
4820         DEBUG(104,("adding a printer at level [%d]\n", level));
4821         dump_a_printer_driver(driver, level);
4822
4823         switch (level) {
4824                 case 3:
4825                         result=add_a_printer_driver_3(driver.info_3);
4826                         break;
4827
4828                 case 6:
4829                         result=add_a_printer_driver_6(driver.info_6);
4830                         break;
4831
4832                 default:
4833                         result=1;
4834                         break;
4835         }
4836
4837         return result;
4838 }
4839 /****************************************************************************
4840 ****************************************************************************/
4841
4842 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
4843                             const char *drivername, const char *architecture,
4844                             uint32_t version)
4845 {
4846         WERROR result;
4847
4848         switch (level) {
4849                 case 3:
4850                         /* Sometime we just want any version of the driver */
4851
4852                         if ( version == DRIVER_ANY_VERSION ) {
4853                                 /* look for Win2k first and then for NT4 */
4854                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4855                                                 architecture, 3);
4856
4857                                 if ( !W_ERROR_IS_OK(result) ) {
4858                                         result = get_a_printer_driver_3( &driver->info_3,
4859                                                         drivername, architecture, 2 );
4860                                 }
4861                         } else {
4862                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4863                                         architecture, version);
4864                         }
4865                         break;
4866
4867                 default:
4868                         result=W_ERROR(1);
4869                         break;
4870         }
4871
4872         if (W_ERROR_IS_OK(result))
4873                 dump_a_printer_driver(*driver, level);
4874
4875         return result;
4876 }
4877
4878 /****************************************************************************
4879 ****************************************************************************/
4880 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4881 {
4882         uint32 result;
4883
4884         switch (level) {
4885                 case 3:
4886                 {
4887                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4888                         if (driver.info_3 != NULL)
4889                         {
4890                                 info3=driver.info_3;
4891                                 SAFE_FREE(info3->dependentfiles);
4892                                 ZERO_STRUCTP(info3);
4893                                 SAFE_FREE(info3);
4894                                 result=0;
4895                         } else {
4896                                 result=4;
4897                         }
4898                         break;
4899                 }
4900                 case 6:
4901                 {
4902                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4903                         if (driver.info_6 != NULL) {
4904                                 info6=driver.info_6;
4905                                 SAFE_FREE(info6->dependentfiles);
4906                                 SAFE_FREE(info6->previousnames);
4907                                 ZERO_STRUCTP(info6);
4908                                 SAFE_FREE(info6);
4909                                 result=0;
4910                         } else {
4911                                 result=4;
4912                         }
4913                         break;
4914                 }
4915                 default:
4916                         result=1;
4917                         break;
4918         }
4919         return result;
4920 }
4921
4922
4923 /****************************************************************************
4924   Determine whether or not a particular driver is currently assigned
4925   to a printer
4926 ****************************************************************************/
4927
4928 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4929 {
4930         int snum;
4931         int n_services = lp_numservices();
4932         NT_PRINTER_INFO_LEVEL *printer = NULL;
4933         bool in_use = False;
4934
4935         if ( !info_3 )
4936                 return False;
4937
4938         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4939
4940         /* loop through the printers.tdb and check for the drivername */
4941
4942         for (snum=0; snum<n_services && !in_use; snum++) {
4943                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4944                         continue;
4945
4946                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4947                         continue;
4948
4949                 if ( strequal(info_3->name, printer->info_2->drivername) )
4950                         in_use = True;
4951
4952                 free_a_printer( &printer, 2 );
4953         }
4954
4955         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4956
4957         if ( in_use ) {
4958                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4959                 WERROR werr;
4960
4961                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4962
4963                 /* we can still remove the driver if there is one of
4964                    "Windows NT x86" version 2 or 3 left */
4965
4966                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4967                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4968                 }
4969                 else {
4970                         switch ( info_3->cversion ) {
4971                         case 2:
4972                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4973                                 break;
4974                         case 3:
4975                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4976                                 break;
4977                         default:
4978                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4979                                         info_3->cversion));
4980                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4981                                 break;
4982                         }
4983                 }
4984
4985                 /* now check the error code */
4986
4987                 if ( W_ERROR_IS_OK(werr) ) {
4988                         /* it's ok to remove the driver, we have other architctures left */
4989                         in_use = False;
4990                         free_a_printer_driver( d, 3 );
4991                 }
4992         }
4993
4994         /* report that the driver is not in use by default */
4995
4996         return in_use;
4997 }
4998
4999
5000 /**********************************************************************
5001  Check to see if a ogiven file is in use by *info
5002  *********************************************************************/
5003
5004 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5005 {
5006         int i = 0;
5007
5008         if ( !info )
5009                 return False;
5010
5011         /* mz: skip files that are in the list but already deleted */
5012         if (!file || !file[0]) {
5013                 return false;
5014         }
5015
5016         if ( strequal(file, info->driverpath) )
5017                 return True;
5018
5019         if ( strequal(file, info->datafile) )
5020                 return True;
5021
5022         if ( strequal(file, info->configfile) )
5023                 return True;
5024
5025         if ( strequal(file, info->helpfile) )
5026                 return True;
5027
5028         /* see of there are any dependent files to examine */
5029
5030         if ( !info->dependentfiles )
5031                 return False;
5032
5033         while ( *info->dependentfiles[i] ) {
5034                 if ( strequal(file, info->dependentfiles[i]) )
5035                         return True;
5036                 i++;
5037         }
5038
5039         return False;
5040
5041 }
5042
5043 /**********************************************************************
5044  Utility function to remove the dependent file pointed to by the
5045  input parameter from the list
5046  *********************************************************************/
5047
5048 static void trim_dependent_file( fstring files[], int idx )
5049 {
5050
5051         /* bump everything down a slot */
5052
5053         while( *files[idx+1] ) {
5054                 fstrcpy( files[idx], files[idx+1] );
5055                 idx++;
5056         }
5057
5058         *files[idx] = '\0';
5059
5060         return;
5061 }
5062
5063 /**********************************************************************
5064  Check if any of the files used by src are also used by drv
5065  *********************************************************************/
5066
5067 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
5068                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
5069 {
5070         bool    in_use = False;
5071         int     i = 0;
5072
5073         if ( !src || !drv )
5074                 return False;
5075
5076         /* check each file.  Remove it from the src structure if it overlaps */
5077
5078         if ( drv_file_in_use(src->driverpath, drv) ) {
5079                 in_use = True;
5080                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
5081                 fstrcpy( src->driverpath, "" );
5082         }
5083
5084         if ( drv_file_in_use(src->datafile, drv) ) {
5085                 in_use = True;
5086                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
5087                 fstrcpy( src->datafile, "" );
5088         }
5089
5090         if ( drv_file_in_use(src->configfile, drv) ) {
5091                 in_use = True;
5092                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5093                 fstrcpy( src->configfile, "" );
5094         }
5095
5096         if ( drv_file_in_use(src->helpfile, drv) ) {
5097                 in_use = True;
5098                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5099                 fstrcpy( src->helpfile, "" );
5100         }
5101
5102         /* are there any dependentfiles to examine? */
5103
5104         if ( !src->dependentfiles )
5105                 return in_use;
5106
5107         while ( *src->dependentfiles[i] ) {
5108                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5109                         in_use = True;
5110                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5111                         trim_dependent_file( src->dependentfiles, i );
5112                 } else
5113                         i++;
5114         }
5115
5116         return in_use;
5117 }
5118
5119 /****************************************************************************
5120   Determine whether or not a particular driver files are currently being
5121   used by any other driver.
5122
5123   Return value is True if any files were in use by other drivers
5124   and False otherwise.
5125
5126   Upon return, *info has been modified to only contain the driver files
5127   which are not in use
5128
5129   Fix from mz:
5130
5131   This needs to check all drivers to ensure that all files in use
5132   have been removed from *info, not just the ones in the first
5133   match.
5134 ****************************************************************************/
5135
5136 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5137 {
5138         int                             i;
5139         int                             ndrivers;
5140         uint32                          version;
5141         fstring                         *list = NULL;
5142         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5143         bool in_use = false;
5144
5145         if ( !info )
5146                 return False;
5147
5148         version = info->cversion;
5149
5150         /* loop over all driver versions */
5151
5152         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5153
5154         /* get the list of drivers */
5155
5156         list = NULL;
5157         ndrivers = get_ntdrivers(&list, info->environment, version);
5158
5159         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5160                 ndrivers, info->environment, version));
5161
5162         /* check each driver for overlap in files */
5163
5164         for (i=0; i<ndrivers; i++) {
5165                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5166
5167                 ZERO_STRUCT(driver);
5168
5169                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5170                         SAFE_FREE(list);
5171                         return True;
5172                 }
5173
5174                 /* check if d2 uses any files from d1 */
5175                 /* only if this is a different driver than the one being deleted */
5176
5177                 if ( !strequal(info->name, driver.info_3->name) ) {
5178                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
5179                                 /* mz: Do not instantly return -
5180                                  * we need to ensure this file isn't
5181                                  * also in use by other drivers. */
5182                                 in_use = true;
5183                         }
5184                 }
5185
5186                 free_a_printer_driver(driver, 3);
5187         }
5188
5189         SAFE_FREE(list);
5190
5191         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5192
5193         driver.info_3 = info;
5194
5195         if ( DEBUGLEVEL >= 20 )
5196                 dump_a_printer_driver( driver, 3 );
5197
5198         return in_use;
5199 }
5200
5201 /****************************************************************************
5202   Actually delete the driver files.  Make sure that
5203   printer_driver_files_in_use() return False before calling
5204   this.
5205 ****************************************************************************/
5206
5207 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5208                                 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
5209 {
5210         int i = 0;
5211         char *s;
5212         const char *file;
5213         connection_struct *conn;
5214         NTSTATUS nt_status;
5215         SMB_STRUCT_STAT  st;
5216         char *oldcwd;
5217         fstring printdollar;
5218         int printdollar_snum;
5219         bool ret = false;
5220
5221         if ( !info_3 )
5222                 return False;
5223
5224         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5225
5226         fstrcpy(printdollar, "print$");
5227
5228         printdollar_snum = find_service(printdollar);
5229         if (printdollar_snum == -1) {
5230                 return false;
5231         }
5232
5233         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5234                                        lp_pathname(printdollar_snum),
5235                                        rpc_pipe->server_info, &oldcwd);
5236         if (!NT_STATUS_IS_OK(nt_status)) {
5237                 DEBUG(0,("delete_driver_files: create_conn_struct "
5238                          "returned %s\n", nt_errstr(nt_status)));
5239                 return false;
5240         }
5241
5242         if ( !CAN_WRITE(conn) ) {
5243                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5244                 goto fail;
5245         }
5246
5247         /* now delete the files; must strip the '\print$' string from
5248            fron of path                                                */
5249
5250         if ( *info_3->driverpath ) {
5251                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5252                         file = s;
5253                         driver_unix_convert(conn,file,&st);
5254                         DEBUG(10,("deleting driverfile [%s]\n", s));
5255                         unlink_internals(conn, NULL, 0, file, False);
5256                 }
5257         }
5258
5259         if ( *info_3->configfile ) {
5260                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5261                         file = s;
5262                         driver_unix_convert(conn,file,&st);
5263                         DEBUG(10,("deleting configfile [%s]\n", s));
5264                         unlink_internals(conn, NULL, 0, file, False);
5265                 }
5266         }
5267
5268         if ( *info_3->datafile ) {
5269                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5270                         file = s;
5271                         driver_unix_convert(conn,file,&st);
5272                         DEBUG(10,("deleting datafile [%s]\n", s));
5273                         unlink_internals(conn, NULL, 0, file, False);
5274                 }
5275         }
5276
5277         if ( *info_3->helpfile ) {
5278                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5279                         file = s;
5280                         driver_unix_convert(conn,file,&st);
5281                         DEBUG(10,("deleting helpfile [%s]\n", s));
5282                         unlink_internals(conn, NULL, 0, file, False);
5283                 }
5284         }
5285
5286         /* check if we are done removing files */
5287
5288         if ( info_3->dependentfiles ) {
5289                 while ( info_3->dependentfiles[i][0] ) {
5290                         char *p;
5291
5292                         /* bypass the "\print$" portion of the path */
5293
5294                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5295                                 file = p;
5296                                 driver_unix_convert(conn,file,&st);
5297                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5298                                 unlink_internals(conn, NULL, 0, file, False);
5299                         }
5300
5301                         i++;
5302                 }
5303         }
5304
5305         goto done;
5306  fail:
5307         ret = false;
5308  done:
5309         if (conn != NULL) {
5310                 vfs_ChDir(conn, oldcwd);
5311                 conn_free_internal(conn);
5312         }
5313         return ret;
5314 }
5315
5316 /****************************************************************************
5317  Remove a printer driver from the TDB.  This assumes that the the driver was
5318  previously looked up.
5319  ***************************************************************************/
5320
5321 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5322                              NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3,
5323                              uint32 version, bool delete_files )
5324 {
5325         char *key = NULL;
5326         const char     *arch;
5327         TDB_DATA        dbuf;
5328         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
5329
5330         /* delete the tdb data first */
5331
5332         arch = get_short_archi(info_3->environment);
5333         if (!arch) {
5334                 return WERR_UNKNOWN_PRINTER_DRIVER;
5335         }
5336         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5337                         arch, version, info_3->name) < 0) {
5338                 return WERR_NOMEM;
5339         }
5340
5341         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5342                 key, delete_files ? "TRUE" : "FALSE" ));
5343
5344         ctr.info_3 = info_3;
5345         dump_a_printer_driver( ctr, 3 );
5346
5347         /* check if the driver actually exists for this environment */
5348
5349         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5350         if ( !dbuf.dptr ) {
5351                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5352                 SAFE_FREE(key);
5353                 return WERR_UNKNOWN_PRINTER_DRIVER;
5354         }
5355
5356         SAFE_FREE( dbuf.dptr );
5357
5358         /* ok... the driver exists so the delete should return success */
5359
5360         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5361                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5362                 SAFE_FREE(key);
5363                 return WERR_ACCESS_DENIED;
5364         }
5365
5366         /*
5367          * now delete any associated files if delete_files == True
5368          * even if this part failes, we return succes because the
5369          * driver doesn not exist any more
5370          */
5371
5372         if ( delete_files )
5373                 delete_driver_files(rpc_pipe, info_3);
5374
5375         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5376         SAFE_FREE(key);
5377
5378         return WERR_OK;
5379 }
5380
5381 /****************************************************************************
5382  Store a security desc for a printer.
5383 ****************************************************************************/
5384
5385 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5386 {
5387         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5388         SEC_DESC_BUF *old_secdesc_ctr = NULL;
5389         TALLOC_CTX *mem_ctx = NULL;
5390         TDB_DATA kbuf;
5391         TDB_DATA dbuf;
5392         DATA_BLOB blob;
5393         WERROR status;
5394         NTSTATUS nt_status;
5395
5396         mem_ctx = talloc_init("nt_printing_setsec");
5397         if (mem_ctx == NULL)
5398                 return WERR_NOMEM;
5399
5400         /* The old owner and group sids of the security descriptor are not
5401            present when new ACEs are added or removed by changing printer
5402            permissions through NT.  If they are NULL in the new security
5403            descriptor then copy them over from the old one. */
5404
5405         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5406                 DOM_SID *owner_sid, *group_sid;
5407                 SEC_ACL *dacl, *sacl;
5408                 SEC_DESC *psd = NULL;
5409                 size_t size;
5410
5411                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5412                         status = WERR_NOMEM;
5413                         goto out;
5414                 }
5415
5416                 /* Pick out correct owner and group sids */
5417
5418                 owner_sid = secdesc_ctr->sd->owner_sid ?
5419                         secdesc_ctr->sd->owner_sid :
5420                         old_secdesc_ctr->sd->owner_sid;
5421
5422                 group_sid = secdesc_ctr->sd->group_sid ?
5423                         secdesc_ctr->sd->group_sid :
5424                         old_secdesc_ctr->sd->group_sid;
5425
5426                 dacl = secdesc_ctr->sd->dacl ?
5427                         secdesc_ctr->sd->dacl :
5428                         old_secdesc_ctr->sd->dacl;
5429
5430                 sacl = secdesc_ctr->sd->sacl ?
5431                         secdesc_ctr->sd->sacl :
5432                         old_secdesc_ctr->sd->sacl;
5433
5434                 /* Make a deep copy of the security descriptor */
5435
5436                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5437                                     owner_sid, group_sid,
5438                                     sacl,
5439                                     dacl,
5440                                     &size);
5441
5442                 if (!psd) {
5443                         status = WERR_NOMEM;
5444                         goto out;
5445                 }
5446
5447                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5448         }
5449
5450         if (!new_secdesc_ctr) {
5451                 new_secdesc_ctr = secdesc_ctr;
5452         }
5453
5454         /* Store the security descriptor in a tdb */
5455
5456         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5457                                           &blob.data, &blob.length);
5458         if (!NT_STATUS_IS_OK(nt_status)) {
5459                 status = ntstatus_to_werror(nt_status);
5460                 goto out;
5461         }
5462
5463         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5464
5465         dbuf.dptr = (unsigned char *)blob.data;
5466         dbuf.dsize = blob.length;
5467
5468         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5469                 status = WERR_OK;
5470         } else {
5471                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5472                 status = WERR_BADFUNC;
5473         }
5474
5475         /* Free malloc'ed memory */
5476         talloc_free(blob.data);
5477
5478  out:
5479
5480         if (mem_ctx)
5481                 talloc_destroy(mem_ctx);
5482         return status;
5483 }
5484
5485 /****************************************************************************
5486  Construct a default security descriptor buffer for a printer.
5487 ****************************************************************************/
5488
5489 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5490 {
5491         SEC_ACE ace[5]; /* max number of ace entries */
5492         int i = 0;
5493         uint32_t sa;
5494         SEC_ACL *psa = NULL;
5495         SEC_DESC_BUF *sdb = NULL;
5496         SEC_DESC *psd = NULL;
5497         DOM_SID adm_sid;
5498         size_t sd_size;
5499
5500         /* Create an ACE where Everyone is allowed to print */
5501
5502         sa = PRINTER_ACE_PRINT;
5503         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5504                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5505
5506         /* Add the domain admins group if we are a DC */
5507
5508         if ( IS_DC ) {
5509                 DOM_SID domadmins_sid;
5510
5511                 sid_copy(&domadmins_sid, get_global_sam_sid());
5512                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5513
5514                 sa = PRINTER_ACE_FULL_CONTROL;
5515                 init_sec_ace(&ace[i++], &domadmins_sid,
5516                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5517                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5518                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5519                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5520         }
5521         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5522                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5523
5524                 sa = PRINTER_ACE_FULL_CONTROL;
5525                 init_sec_ace(&ace[i++], &adm_sid,
5526                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5527                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5528                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5529                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5530         }
5531
5532         /* add BUILTIN\Administrators as FULL CONTROL */
5533
5534         sa = PRINTER_ACE_FULL_CONTROL;
5535         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5536                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5537                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5538         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5539                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5540                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5541
5542         /* Make the security descriptor owned by the BUILTIN\Administrators */
5543
5544         /* The ACL revision number in rpc_secdesc.h differs from the one
5545            created by NT when setting ACE entries in printer
5546            descriptors.  NT4 complains about the property being edited by a
5547            NT5 machine. */
5548
5549         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5550                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5551                         &global_sid_Builtin_Administrators,
5552                         &global_sid_Builtin_Administrators,
5553                         NULL, psa, &sd_size);
5554         }
5555
5556         if (!psd) {
5557                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5558                 return NULL;
5559         }
5560
5561         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5562
5563         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5564                  (unsigned int)sd_size));
5565
5566         return sdb;
5567 }
5568
5569 /****************************************************************************
5570  Get a security desc for a printer.
5571 ****************************************************************************/
5572
5573 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5574 {
5575         TDB_DATA kbuf;
5576         TDB_DATA dbuf;
5577         DATA_BLOB blob;
5578         char *temp;
5579         NTSTATUS status;
5580
5581         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5582                 sharename = temp + 1;
5583         }
5584
5585         /* Fetch security descriptor from tdb */
5586
5587         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5588
5589         dbuf = tdb_fetch(tdb_printers, kbuf);
5590         if (dbuf.dptr) {
5591
5592                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5593                                                  secdesc_ctr);
5594                 SAFE_FREE(dbuf.dptr);
5595
5596                 if (NT_STATUS_IS_OK(status)) {
5597                         return true;
5598                 }
5599         }
5600
5601         *secdesc_ctr = construct_default_printer_sdb(ctx);
5602         if (!*secdesc_ctr) {
5603                 return false;
5604         }
5605
5606         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5607                                        &blob.data, &blob.length);
5608         if (NT_STATUS_IS_OK(status)) {
5609                 dbuf.dptr = (unsigned char *)blob.data;
5610                 dbuf.dsize = blob.length;
5611                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5612                 talloc_free(blob.data);
5613         }
5614
5615         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5616            this security descriptor has been created when winbindd was
5617            down.  Take ownership of security descriptor. */
5618
5619         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5620                 DOM_SID owner_sid;
5621
5622                 /* Change sd owner to workgroup administrator */
5623
5624                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5625                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5626                         SEC_DESC *psd = NULL;
5627                         size_t size;
5628
5629                         /* Create new sd */
5630
5631                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5632
5633                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5634                                             &owner_sid,
5635                                             (*secdesc_ctr)->sd->group_sid,
5636                                             (*secdesc_ctr)->sd->sacl,
5637                                             (*secdesc_ctr)->sd->dacl,
5638                                             &size);
5639
5640                         if (!psd) {
5641                                 return False;
5642                         }
5643
5644                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5645                         if (!new_secdesc_ctr) {
5646                                 return False;
5647                         }
5648
5649                         /* Swap with other one */
5650
5651                         *secdesc_ctr = new_secdesc_ctr;
5652
5653                         /* Set it */
5654
5655                         nt_printing_setsec(sharename, *secdesc_ctr);
5656                 }
5657         }
5658
5659         if (DEBUGLEVEL >= 10) {
5660                 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5661                 int i;
5662
5663                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5664                            sharename, the_acl->num_aces));
5665
5666                 for (i = 0; i < the_acl->num_aces; i++) {
5667                         DEBUG(10, ("%s %d %d 0x%08x\n",
5668                                    sid_string_dbg(&the_acl->aces[i].trustee),
5669                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5670                                    the_acl->aces[i].access_mask));
5671                 }
5672         }
5673
5674         return True;
5675 }
5676
5677 /* error code:
5678         0: everything OK
5679         1: level not implemented
5680         2: file doesn't exist
5681         3: can't allocate memory
5682         4: can't free memory
5683         5: non existant struct
5684 */
5685
5686 /*
5687         A printer and a printer driver are 2 different things.
5688         NT manages them separatelly, Samba does the same.
5689         Why ? Simply because it's easier and it makes sense !
5690
5691         Now explanation: You have 3 printers behind your samba server,
5692         2 of them are the same make and model (laser A and B). But laser B
5693         has an 3000 sheet feeder and laser A doesn't such an option.
5694         Your third printer is an old dot-matrix model for the accounting :-).
5695
5696         If the /usr/local/samba/lib directory (default dir), you will have
5697         5 files to describe all of this.
5698
5699         3 files for the printers (1 by printer):
5700                 NTprinter_laser A
5701                 NTprinter_laser B
5702                 NTprinter_accounting
5703         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5704                 NTdriver_printer model X
5705                 NTdriver_printer model Y
5706
5707 jfm: I should use this comment for the text file to explain
5708         same thing for the forms BTW.
5709         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5710
5711 */
5712
5713 /* Convert generic access rights to printer object specific access rights.
5714    It turns out that NT4 security descriptors use generic access rights and
5715    NT5 the object specific ones. */
5716
5717 void map_printer_permissions(SEC_DESC *sd)
5718 {
5719         int i;
5720
5721         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5722                 se_map_generic(&sd->dacl->aces[i].access_mask,
5723                                &printer_generic_mapping);
5724         }
5725 }
5726
5727 void map_job_permissions(SEC_DESC *sd)
5728 {
5729         int i;
5730
5731         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5732                 se_map_generic(&sd->dacl->aces[i].access_mask,
5733                                &job_generic_mapping);
5734         }
5735 }
5736
5737
5738 /****************************************************************************
5739  Check a user has permissions to perform the given operation.  We use the
5740  permission constants defined in include/rpc_spoolss.h to check the various
5741  actions we perform when checking printer access.
5742
5743    PRINTER_ACCESS_ADMINISTER:
5744        print_queue_pause, print_queue_resume, update_printer_sec,
5745        update_printer, spoolss_addprinterex_level_2,
5746        _spoolss_setprinterdata
5747
5748    PRINTER_ACCESS_USE:
5749        print_job_start
5750
5751    JOB_ACCESS_ADMINISTER:
5752        print_job_delete, print_job_pause, print_job_resume,
5753        print_queue_purge
5754
5755   Try access control in the following order (for performance reasons):
5756     1)  root ans SE_PRINT_OPERATOR can do anything (easy check)
5757     2)  check security descriptor (bit comparisons in memory)
5758     3)  "printer admins" (may result in numerous calls to winbind)
5759
5760  ****************************************************************************/
5761 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5762                         int access_type)
5763 {
5764         SEC_DESC_BUF *secdesc = NULL;
5765         uint32 access_granted;
5766         NTSTATUS status;
5767         const char *pname;
5768         TALLOC_CTX *mem_ctx = NULL;
5769         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5770
5771         /* If user is NULL then use the current_user structure */
5772
5773         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5774
5775         if (server_info->utok.uid == 0
5776             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5777                 return True;
5778         }
5779
5780         /* Get printer name */
5781
5782         pname = PRINTERNAME(snum);
5783
5784         if (!pname || !*pname) {
5785                 errno = EACCES;
5786                 return False;
5787         }
5788
5789         /* Get printer security descriptor */
5790
5791         if(!(mem_ctx = talloc_init("print_access_check"))) {
5792                 errno = ENOMEM;
5793                 return False;
5794         }
5795
5796         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5797                 talloc_destroy(mem_ctx);
5798                 errno = ENOMEM;
5799                 return False;
5800         }
5801
5802         if (access_type == JOB_ACCESS_ADMINISTER) {
5803                 SEC_DESC_BUF *parent_secdesc = secdesc;
5804
5805                 /* Create a child security descriptor to check permissions
5806                    against.  This is because print jobs are child objects
5807                    objects of a printer. */
5808
5809                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5810
5811                 if (!NT_STATUS_IS_OK(status)) {
5812                         talloc_destroy(mem_ctx);
5813                         errno = map_errno_from_nt_status(status);
5814                         return False;
5815                 }
5816
5817                 map_job_permissions(secdesc->sd);
5818         } else {
5819                 map_printer_permissions(secdesc->sd);
5820         }
5821
5822         /* Check access */
5823         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5824                                  &access_granted);
5825
5826         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5827
5828         /* see if we need to try the printer admin list */
5829
5830         if ((access_granted == 0) &&
5831             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5832                                          NULL, NULL, server_info->ptok,
5833                                          lp_printer_admin(snum)))) {
5834                 talloc_destroy(mem_ctx);
5835                 return True;
5836         }
5837
5838         talloc_destroy(mem_ctx);
5839
5840         if (!NT_STATUS_IS_OK(status)) {
5841                 errno = EACCES;
5842         }
5843
5844         return NT_STATUS_IS_OK(status);
5845 }
5846
5847 /****************************************************************************
5848  Check the time parameters allow a print operation.
5849 *****************************************************************************/
5850
5851 bool print_time_access_check(const char *servicename)
5852 {
5853         NT_PRINTER_INFO_LEVEL *printer = NULL;
5854         bool ok = False;
5855         time_t now = time(NULL);
5856         struct tm *t;
5857         uint32 mins;
5858
5859         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5860                 return False;
5861
5862         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5863                 ok = True;
5864
5865         t = gmtime(&now);
5866         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5867
5868         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5869                 ok = True;
5870
5871         free_a_printer(&printer, 2);
5872
5873         if (!ok)
5874                 errno = EACCES;
5875
5876         return ok;
5877 }
5878
5879 /****************************************************************************
5880  Fill in the servername sent in the _spoolss_open_printer_ex() call
5881 ****************************************************************************/
5882
5883 char* get_server_name( Printer_entry *printer )
5884 {
5885         return printer->servername;
5886 }
5887
5888