Add missing header, remove generated header
[sfrench/samba-autobuild/.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
3247         /* build the ads mods */
3248         ctx = talloc_init("nt_printer_publish_ads");
3249         if (ctx == NULL) {
3250                 return WERR_NOMEM;
3251         }
3252
3253         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3254
3255         /* figure out where to publish */
3256         ads_find_machine_acct(ads, &res, global_myname());
3257
3258         /* We use ldap_get_dn here as we need the answer
3259          * in utf8 to call ldap_explode_dn(). JRA. */
3260
3261         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3262         if (!srv_dn_utf8) {
3263                 TALLOC_FREE(ctx);
3264                 return WERR_SERVER_UNAVAILABLE;
3265         }
3266         ads_msgfree(ads, res);
3267         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3268         if (!srv_cn_utf8) {
3269                 TALLOC_FREE(ctx);
3270                 ldap_memfree(srv_dn_utf8);
3271                 return WERR_SERVER_UNAVAILABLE;
3272         }
3273         /* Now convert to CH_UNIX. */
3274         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3275                 TALLOC_FREE(ctx);
3276                 ldap_memfree(srv_dn_utf8);
3277                 ldap_memfree(srv_cn_utf8);
3278                 return WERR_SERVER_UNAVAILABLE;
3279         }
3280         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3281                 TALLOC_FREE(ctx);
3282                 ldap_memfree(srv_dn_utf8);
3283                 ldap_memfree(srv_cn_utf8);
3284                 TALLOC_FREE(srv_dn);
3285                 return WERR_SERVER_UNAVAILABLE;
3286         }
3287
3288         ldap_memfree(srv_dn_utf8);
3289         ldap_memfree(srv_cn_utf8);
3290
3291         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3292         if (!srv_cn_escaped) {
3293                 TALLOC_FREE(ctx);
3294                 return WERR_SERVER_UNAVAILABLE;
3295         }
3296         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3297         if (!sharename_escaped) {
3298                 SAFE_FREE(srv_cn_escaped);
3299                 TALLOC_FREE(ctx);
3300                 return WERR_SERVER_UNAVAILABLE;
3301         }
3302
3303         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3304
3305         SAFE_FREE(srv_cn_escaped);
3306         SAFE_FREE(sharename_escaped);
3307
3308         mods = ads_init_mods(ctx);
3309
3310         if (mods == NULL) {
3311                 SAFE_FREE(prt_dn);
3312                 TALLOC_FREE(ctx);
3313                 return WERR_NOMEM;
3314         }
3315
3316         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3317         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3318                     printer->info_2->sharename);
3319
3320         /* publish it */
3321         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3322         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3323                 int i;
3324                 for (i=0; mods[i] != 0; i++)
3325                         ;
3326                 mods[i] = (LDAPMod *)-1;
3327                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3328         }
3329
3330         if (!ADS_ERR_OK(ads_rc))
3331                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3332
3333         /* retreive the guid and store it locally */
3334         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3335                 ZERO_STRUCT(guid);
3336                 ads_pull_guid(ads, res, &guid);
3337                 ads_msgfree(ads, res);
3338                 store_printer_guid(printer->info_2, guid);
3339                 win_rc = mod_a_printer(printer, 2);
3340         }
3341         TALLOC_FREE(ctx);
3342
3343         return win_rc;
3344 }
3345
3346 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3347                                        NT_PRINTER_INFO_LEVEL *printer)
3348 {
3349         ADS_STATUS ads_rc;
3350         LDAPMessage *res = NULL;
3351         char *prt_dn = NULL;
3352
3353         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3354
3355         /* remove the printer from the directory */
3356         ads_rc = ads_find_printer_on_server(ads, &res,
3357                             printer->info_2->sharename, global_myname());
3358
3359         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3360                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3361                 if (!prt_dn) {
3362                         ads_msgfree(ads, res);
3363                         return WERR_NOMEM;
3364                 }
3365                 ads_rc = ads_del_dn(ads, prt_dn);
3366                 TALLOC_FREE(prt_dn);
3367         }
3368
3369         if (res) {
3370                 ads_msgfree(ads, res);
3371         }
3372         return WERR_OK;
3373 }
3374
3375 /****************************************************************************
3376  * Publish a printer in the directory
3377  *
3378  * @param snum describing printer service
3379  * @return WERROR indicating status of publishing
3380  ***************************************************************************/
3381
3382 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3383 {
3384         ADS_STATUS ads_rc;
3385         ADS_STRUCT *ads = NULL;
3386         NT_PRINTER_INFO_LEVEL *printer = NULL;
3387         WERROR win_rc;
3388
3389         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3390         if (!W_ERROR_IS_OK(win_rc))
3391                 goto done;
3392
3393         switch (action) {
3394         case DSPRINT_PUBLISH:
3395         case DSPRINT_UPDATE:
3396                 /* set the DsSpooler info and attributes */
3397                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3398                         win_rc = WERR_NOMEM;
3399                         goto done;
3400                 }
3401
3402                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3403                 break;
3404         case DSPRINT_UNPUBLISH:
3405                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3406                 break;
3407         default:
3408                 win_rc = WERR_NOT_SUPPORTED;
3409                 goto done;
3410         }
3411
3412         win_rc = mod_a_printer(printer, 2);
3413         if (!W_ERROR_IS_OK(win_rc)) {
3414                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3415                 goto done;
3416         }
3417
3418         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3419         if (!ads) {
3420                 DEBUG(3, ("ads_init() failed\n"));
3421                 win_rc = WERR_SERVER_UNAVAILABLE;
3422                 goto done;
3423         }
3424         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3425         SAFE_FREE(ads->auth.password);
3426         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3427                 NULL, NULL);
3428
3429         /* ads_connect() will find the DC for us */
3430         ads_rc = ads_connect(ads);
3431         if (!ADS_ERR_OK(ads_rc)) {
3432                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3433                 win_rc = WERR_ACCESS_DENIED;
3434                 goto done;
3435         }
3436
3437         switch (action) {
3438         case DSPRINT_PUBLISH:
3439         case DSPRINT_UPDATE:
3440                 win_rc = nt_printer_publish_ads(ads, printer);
3441                 break;
3442         case DSPRINT_UNPUBLISH:
3443                 win_rc = nt_printer_unpublish_ads(ads, printer);
3444                 break;
3445         }
3446
3447 done:
3448         free_a_printer(&printer, 2);
3449         ads_destroy(&ads);
3450         return win_rc;
3451 }
3452
3453 WERROR check_published_printers(void)
3454 {
3455         ADS_STATUS ads_rc;
3456         ADS_STRUCT *ads = NULL;
3457         int snum;
3458         int n_services = lp_numservices();
3459         NT_PRINTER_INFO_LEVEL *printer = NULL;
3460
3461         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3462         if (!ads) {
3463                 DEBUG(3, ("ads_init() failed\n"));
3464                 return WERR_SERVER_UNAVAILABLE;
3465         }
3466         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3467         SAFE_FREE(ads->auth.password);
3468         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3469                 NULL, NULL);
3470
3471         /* ads_connect() will find the DC for us */
3472         ads_rc = ads_connect(ads);
3473         if (!ADS_ERR_OK(ads_rc)) {
3474                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3475                 ads_destroy(&ads);
3476                 ads_kdestroy("MEMORY:prtpub_cache");
3477                 return WERR_ACCESS_DENIED;
3478         }
3479
3480         for (snum = 0; snum < n_services; snum++) {
3481                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3482                         continue;
3483
3484                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3485                                                 lp_servicename(snum))) &&
3486                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3487                         nt_printer_publish_ads(ads, printer);
3488
3489                 free_a_printer(&printer, 2);
3490         }
3491
3492         ads_destroy(&ads);
3493         ads_kdestroy("MEMORY:prtpub_cache");
3494         return WERR_OK;
3495 }
3496
3497 bool is_printer_published(Printer_entry *print_hnd, int snum,
3498                           struct GUID *guid)
3499 {
3500         NT_PRINTER_INFO_LEVEL *printer = NULL;
3501         REGVAL_CTR *ctr;
3502         REGISTRY_VALUE *guid_val;
3503         WERROR win_rc;
3504         int i;
3505         bool ret = False;
3506
3507         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3508
3509         if (!W_ERROR_IS_OK(win_rc) ||
3510             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3511             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3512             !(ctr = printer->info_2->data->keys[i].values) ||
3513             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3514         {
3515                 free_a_printer(&printer, 2);
3516                 return False;
3517         }
3518
3519         /* fetching printer guids really ought to be a separate function. */
3520
3521         if ( guid ) {
3522                 fstring guid_str;
3523
3524                 /* We used to store the guid as REG_BINARY, then swapped
3525                    to REG_SZ for Vista compatibility so check for both */
3526
3527                 switch ( regval_type(guid_val) ){
3528                 case REG_SZ:
3529                         rpcstr_pull( guid_str, regval_data_p(guid_val),
3530                                      sizeof(guid_str)-1, -1, STR_TERMINATE );
3531                         ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3532                         break;
3533                 case REG_BINARY:
3534                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3535                                 ret = False;
3536                                 break;
3537                         }
3538                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3539                         break;
3540                 default:
3541                         DEBUG(0,("is_printer_published: GUID value stored as "
3542                                  "invaluid type (%d)\n", regval_type(guid_val) ));
3543                         break;
3544                 }
3545         }
3546
3547         free_a_printer(&printer, 2);
3548         return ret;
3549 }
3550 #else
3551 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3552 {
3553         return WERR_OK;
3554 }
3555
3556 WERROR check_published_printers(void)
3557 {
3558         return WERR_OK;
3559 }
3560
3561 bool is_printer_published(Printer_entry *print_hnd, int snum,
3562                           struct GUID *guid)
3563 {
3564         return False;
3565 }
3566 #endif /* HAVE_ADS */
3567
3568 /****************************************************************************
3569  ***************************************************************************/
3570
3571 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3572 {
3573         NT_PRINTER_DATA *data;
3574         int             i;
3575         int             removed_keys = 0;
3576         int             empty_slot;
3577
3578         data = p2->data;
3579         empty_slot = data->num_keys;
3580
3581         if ( !key )
3582                 return WERR_INVALID_PARAM;
3583
3584         /* remove all keys */
3585
3586         if ( !strlen(key) ) {
3587
3588                 TALLOC_FREE( data );
3589
3590                 p2->data = NULL;
3591
3592                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3593                         p2->printername ));
3594
3595                 return WERR_OK;
3596         }
3597
3598         /* remove a specific key (and all subkeys) */
3599
3600         for ( i=0; i<data->num_keys; i++ ) {
3601                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3602                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3603                                 data->keys[i].name));
3604
3605                         TALLOC_FREE( data->keys[i].name );
3606                         TALLOC_FREE( data->keys[i].values );
3607
3608                         /* mark the slot as empty */
3609
3610                         ZERO_STRUCTP( &data->keys[i] );
3611                 }
3612         }
3613
3614         /* find the first empty slot */
3615
3616         for ( i=0; i<data->num_keys; i++ ) {
3617                 if ( !data->keys[i].name ) {
3618                         empty_slot = i;
3619                         removed_keys++;
3620                         break;
3621                 }
3622         }
3623
3624         if ( i == data->num_keys )
3625                 /* nothing was removed */
3626                 return WERR_INVALID_PARAM;
3627
3628         /* move everything down */
3629
3630         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3631                 if ( data->keys[i].name ) {
3632                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3633                         ZERO_STRUCTP( &data->keys[i] );
3634                         empty_slot++;
3635                         removed_keys++;
3636                 }
3637         }
3638
3639         /* update count */
3640
3641         data->num_keys -= removed_keys;
3642
3643         /* sanity check to see if anything is left */
3644
3645         if ( !data->num_keys ) {
3646                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3647
3648                 SAFE_FREE( data->keys );
3649                 ZERO_STRUCTP( data );
3650         }
3651
3652         return WERR_OK;
3653 }
3654
3655 /****************************************************************************
3656  ***************************************************************************/
3657
3658 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3659 {
3660         WERROR          result = WERR_OK;
3661         int             key_index;
3662
3663         /* we must have names on non-zero length */
3664
3665         if ( !key || !*key|| !value || !*value )
3666                 return WERR_INVALID_NAME;
3667
3668         /* find the printer key first */
3669
3670         key_index = lookup_printerkey( p2->data, key );
3671         if ( key_index == -1 )
3672                 return WERR_OK;
3673
3674         /* make sure the value exists so we can return the correct error code */
3675
3676         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3677                 return WERR_BADFILE;
3678
3679         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3680
3681         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3682                 key, value ));
3683
3684         return result;
3685 }
3686
3687 /****************************************************************************
3688  ***************************************************************************/
3689
3690 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3691                            uint32 type, uint8 *data, int real_len )
3692 {
3693         WERROR          result = WERR_OK;
3694         int             key_index;
3695
3696         /* we must have names on non-zero length */
3697
3698         if ( !key || !*key|| !value || !*value )
3699                 return WERR_INVALID_NAME;
3700
3701         /* find the printer key first */
3702
3703         key_index = lookup_printerkey( p2->data, key );
3704         if ( key_index == -1 )
3705                 key_index = add_new_printer_key( p2->data, key );
3706
3707         if ( key_index == -1 )
3708                 return WERR_NOMEM;
3709
3710         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3711                 type, (const char *)data, real_len );
3712
3713         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3714                 key, value, type, real_len  ));
3715
3716         return result;
3717 }
3718
3719 /****************************************************************************
3720  ***************************************************************************/
3721
3722 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3723 {
3724         int             key_index;
3725
3726         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3727                 return NULL;
3728
3729         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3730                 key, value ));
3731
3732         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3733 }
3734
3735 /****************************************************************************
3736  Unpack a list of registry values frem the TDB
3737  ***************************************************************************/
3738
3739 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3740 {
3741         int             len = 0;
3742         uint32          type;
3743         fstring string;
3744         const char *valuename = NULL;
3745         const char *keyname = NULL;
3746         char            *str;
3747         int             size;
3748         uint8           *data_p;
3749         REGISTRY_VALUE  *regval_p;
3750         int             key_index;
3751
3752         /* add the "PrinterDriverData" key first for performance reasons */
3753
3754         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3755
3756         /* loop and unpack the rest of the registry values */
3757
3758         while ( True ) {
3759
3760                 /* check to see if there are any more registry values */
3761
3762                 regval_p = NULL;
3763                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3764                 if ( !regval_p )
3765                         break;
3766
3767                 /* unpack the next regval */
3768
3769                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3770                                   string,
3771                                   &type,
3772                                   &size,
3773                                   &data_p);
3774
3775                 /* lookup for subkey names which have a type of REG_NONE */
3776                 /* there's no data with this entry */
3777
3778                 if ( type == REG_NONE ) {
3779                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3780                                 add_new_printer_key( printer_data, string );
3781                         continue;
3782                 }
3783
3784                 /*
3785                  * break of the keyname from the value name.
3786                  * Valuenames can have embedded '\'s so be careful.
3787                  * only support one level of keys.  See the
3788                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3789                  * -- jerry
3790                  */
3791
3792                 str = strchr_m( string, '\\');
3793
3794                 /* Put in "PrinterDriverData" is no key specified */
3795
3796                 if ( !str ) {
3797                         keyname = SPOOL_PRINTERDATA_KEY;
3798                         valuename = string;
3799                 }
3800                 else {
3801                         *str = '\0';
3802                         keyname = string;
3803                         valuename = str+1;
3804                 }
3805
3806                 /* see if we need a new key */
3807
3808                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3809                         key_index = add_new_printer_key( printer_data, keyname );
3810
3811                 if ( key_index == -1 ) {
3812                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3813                                 keyname));
3814                         break;
3815                 }
3816
3817                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3818
3819                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3820                    Thanks to Martin Zielinski for the hint. */
3821
3822                 if ( type == REG_BINARY &&
3823                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3824                      strequal( valuename, "objectGUID" ) )
3825                 {
3826                         struct GUID guid;
3827                         UNISTR2 unistr_guid;
3828
3829                         ZERO_STRUCT( unistr_guid );
3830
3831                         /* convert the GUID to a UNICODE string */
3832
3833                         memcpy( &guid, data_p, sizeof(struct GUID) );
3834
3835                         init_unistr2( &unistr_guid,
3836                                       GUID_string(talloc_tos(), &guid),
3837                                       UNI_STR_TERMINATE );
3838
3839                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3840                                              valuename, REG_SZ,
3841                                              (const char *)unistr_guid.buffer,
3842                                              unistr_guid.uni_str_len*2 );
3843
3844                 } else {
3845                         /* add the value */
3846
3847                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3848                                              valuename, type, (const char *)data_p,
3849                                              size );
3850                 }
3851
3852                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3853
3854         }
3855
3856         return len;
3857 }
3858
3859 /****************************************************************************
3860  ***************************************************************************/
3861
3862 static char *last_from;
3863 static char *last_to;
3864
3865 static const char *get_last_from(void)
3866 {
3867         if (!last_from) {
3868                 return "";
3869         }
3870         return last_from;
3871 }
3872
3873 static const char *get_last_to(void)
3874 {
3875         if (!last_to) {
3876                 return "";
3877         }
3878         return last_to;
3879 }
3880
3881 static bool set_last_from_to(const char *from, const char *to)
3882 {
3883         char *orig_from = last_from;
3884         char *orig_to = last_to;
3885
3886         last_from = SMB_STRDUP(from);
3887         last_to = SMB_STRDUP(to);
3888
3889         SAFE_FREE(orig_from);
3890         SAFE_FREE(orig_to);
3891
3892         if (!last_from || !last_to) {
3893                 SAFE_FREE(last_from);
3894                 SAFE_FREE(last_to);
3895                 return false;
3896         }
3897         return true;
3898 }
3899
3900 static void map_to_os2_driver(fstring drivername)
3901 {
3902         char *mapfile = lp_os2_driver_map();
3903         char **lines = NULL;
3904         int numlines = 0;
3905         int i;
3906
3907         if (!strlen(drivername))
3908                 return;
3909
3910         if (!*mapfile)
3911                 return;
3912
3913         if (strequal(drivername,get_last_from())) {
3914                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3915                         drivername,get_last_to()));
3916                 fstrcpy(drivername,get_last_to());
3917                 return;
3918         }
3919
3920         lines = file_lines_load(mapfile, &numlines,0,NULL);
3921         if (numlines == 0 || lines == NULL) {
3922                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3923                 TALLOC_FREE(lines);
3924                 return;
3925         }
3926
3927         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3928
3929         for( i = 0; i < numlines; i++) {
3930                 char *nt_name = lines[i];
3931                 char *os2_name = strchr(nt_name,'=');
3932
3933                 if (!os2_name)
3934                         continue;
3935
3936                 *os2_name++ = 0;
3937
3938                 while (isspace(*nt_name))
3939                         nt_name++;
3940
3941                 if (!*nt_name || strchr("#;",*nt_name))
3942                         continue;
3943
3944                 {
3945                         int l = strlen(nt_name);
3946                         while (l && isspace(nt_name[l-1])) {
3947                                 nt_name[l-1] = 0;
3948                                 l--;
3949                         }
3950                 }
3951
3952                 while (isspace(*os2_name))
3953                         os2_name++;
3954
3955                 {
3956                         int l = strlen(os2_name);
3957                         while (l && isspace(os2_name[l-1])) {
3958                                 os2_name[l-1] = 0;
3959                                 l--;
3960                         }
3961                 }
3962
3963                 if (strequal(nt_name,drivername)) {
3964                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3965                         set_last_from_to(drivername,os2_name);
3966                         fstrcpy(drivername,os2_name);
3967                         TALLOC_FREE(lines);
3968                         return;
3969                 }
3970         }
3971
3972         TALLOC_FREE(lines);
3973 }
3974
3975 /****************************************************************************
3976  Get a default printer info 2 struct.
3977 ****************************************************************************/
3978
3979 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3980                                 const char *servername,
3981                                 const char* sharename,
3982                                 bool get_loc_com)
3983 {
3984         int snum = lp_servicenumber(sharename);
3985
3986         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3987         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3988                 servername, sharename);
3989         fstrcpy(info->sharename, sharename);
3990         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3991
3992         /* by setting the driver name to an empty string, a local NT admin
3993            can now run the **local** APW to install a local printer driver
3994            for a Samba shared printer in 2.2.  Without this, drivers **must** be
3995            installed on the Samba server for NT clients --jerry */
3996 #if 0   /* JERRY --do not uncomment-- */
3997         if (!*info->drivername)
3998                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3999 #endif
4000
4001
4002         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4003
4004         strlcpy(info->comment, "", sizeof(info->comment));
4005         fstrcpy(info->printprocessor, "winprint");
4006         fstrcpy(info->datatype, "RAW");
4007
4008 #ifdef HAVE_CUPS
4009         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4010                 /* Pull the location and comment strings from cups if we don't
4011                    already have one */
4012                 if ( !strlen(info->location) || !strlen(info->comment) )
4013                         cups_pull_comment_location( info );
4014         }
4015 #endif
4016
4017         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4018
4019         info->starttime = 0; /* Minutes since 12:00am GMT */
4020         info->untiltime = 0; /* Minutes since 12:00am GMT */
4021         info->priority = 1;
4022         info->default_priority = 1;
4023         info->setuptime = (uint32)time(NULL);
4024
4025         /*
4026          * I changed this as I think it is better to have a generic
4027          * DEVMODE than to crash Win2k explorer.exe   --jerry
4028          * See the HP Deskjet 990c Win2k drivers for an example.
4029          *
4030          * However the default devmode appears to cause problems
4031          * with the HP CLJ 8500 PCL driver.  Hence the addition of
4032          * the "default devmode" parameter   --jerry 22/01/2002
4033          */
4034
4035         if (lp_default_devmode(snum)) {
4036                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4037                         goto fail;
4038                 }
4039         } else {
4040                 info->devmode = NULL;
4041         }
4042
4043         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4044                 goto fail;
4045         }
4046
4047         return WERR_OK;
4048
4049 fail:
4050         if (info->devmode)
4051                 free_nt_devicemode(&info->devmode);
4052
4053         return WERR_ACCESS_DENIED;
4054 }
4055
4056 /****************************************************************************
4057 ****************************************************************************/
4058
4059 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4060                                 const char *servername,
4061                                 const char *sharename,
4062                                 bool get_loc_com)
4063 {
4064         int len = 0;
4065         int snum = lp_servicenumber(sharename);
4066         TDB_DATA kbuf, dbuf;
4067         fstring printername;
4068         char adevice[MAXDEVICENAME];
4069         char *comment = NULL;
4070
4071         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4072
4073         dbuf = tdb_fetch(tdb_printers, kbuf);
4074         if (!dbuf.dptr) {
4075                 return get_a_printer_2_default(info, servername,
4076                                         sharename, get_loc_com);
4077         }
4078
4079         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4080                         &info->attributes,
4081                         &info->priority,
4082                         &info->default_priority,
4083                         &info->starttime,
4084                         &info->untiltime,
4085                         &info->status,
4086                         &info->cjobs,
4087                         &info->averageppm,
4088                         &info->changeid,
4089                         &info->c_setprinter,
4090                         &info->setuptime,
4091                         info->servername,
4092                         info->printername,
4093                         info->sharename,
4094                         info->portname,
4095                         info->drivername,
4096                         &comment,
4097                         info->location,
4098                         info->sepfile,
4099                         info->printprocessor,
4100                         info->datatype,
4101                         info->parameters);
4102
4103         if (comment) {
4104                 strlcpy(info->comment, comment, sizeof(info->comment));
4105                 SAFE_FREE(comment);
4106         }
4107
4108         /* Samba has to have shared raw drivers. */
4109         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4110         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4111
4112         /* Restore the stripped strings. */
4113         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4114
4115         if ( lp_force_printername(snum) ) {
4116                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4117         } else {
4118                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4119         }
4120
4121         fstrcpy(info->printername, printername);
4122
4123 #ifdef HAVE_CUPS
4124         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4125                 /* Pull the location and comment strings from cups if we don't
4126                    already have one */
4127                 if ( !strlen(info->location) || !strlen(info->comment) )
4128                         cups_pull_comment_location( info );
4129         }
4130 #endif
4131
4132         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4133
4134         /*
4135          * Some client drivers freak out if there is a NULL devmode
4136          * (probably the driver is not checking before accessing
4137          * the devmode pointer)   --jerry
4138          *
4139          * See comments in get_a_printer_2_default()
4140          */
4141
4142         if (lp_default_devmode(snum) && !info->devmode) {
4143                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4144                         printername));
4145                 info->devmode = construct_nt_devicemode(printername);
4146         }
4147
4148         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4149         if (info->devmode) {
4150                 fstrcpy(info->devmode->devicename, adevice);
4151         }
4152
4153         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4154                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4155                 SAFE_FREE(dbuf.dptr);
4156                 return WERR_NOMEM;
4157         }
4158         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4159
4160         /* This will get the current RPC talloc context, but we should be
4161            passing this as a parameter... fixme... JRA ! */
4162
4163         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4164                 SAFE_FREE(dbuf.dptr);
4165                 return WERR_NOMEM;
4166         }
4167
4168         /* Fix for OS/2 drivers. */
4169
4170         if (get_remote_arch() == RA_OS2) {
4171                 map_to_os2_driver(info->drivername);
4172         }
4173
4174         SAFE_FREE(dbuf.dptr);
4175
4176         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4177                  sharename, info->printername, info->drivername));
4178
4179         return WERR_OK;
4180 }
4181
4182 /****************************************************************************
4183  Debugging function, dump at level 6 the struct in the logs.
4184 ****************************************************************************/
4185 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4186 {
4187         uint32 result;
4188         NT_PRINTER_INFO_LEVEL_2 *info2;
4189
4190         DEBUG(106,("Dumping printer at level [%d]\n", level));
4191
4192         switch (level) {
4193                 case 2:
4194                 {
4195                         if (printer->info_2 == NULL)
4196                                 result=5;
4197                         else
4198                         {
4199                                 info2=printer->info_2;
4200
4201                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4202                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4203                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4204                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4205                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4206                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4207                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4208                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4209                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4210                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4211                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4212
4213                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4214                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4215                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4216                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4217                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4218                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4219                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4220                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4221                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4222                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4223                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4224                                 result=0;
4225                         }
4226                         break;
4227                 }
4228                 default:
4229                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4230                         result=1;
4231                         break;
4232         }
4233
4234         return result;
4235 }
4236
4237 /****************************************************************************
4238  Update the changeid time.
4239  This is SO NASTY as some drivers need this to change, others need it
4240  static. This value will change every second, and I must hope that this
4241  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4242  UTAH ! JRA.
4243 ****************************************************************************/
4244
4245 static uint32 rev_changeid(void)
4246 {
4247         struct timeval tv;
4248
4249         get_process_uptime(&tv);
4250
4251 #if 1   /* JERRY */
4252         /* Return changeid as msec since spooler restart */
4253         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4254 #else
4255         /*
4256          * This setting seems to work well but is too untested
4257          * to replace the above calculation.  Left in for experiementation
4258          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4259          */
4260         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4261 #endif
4262 }
4263
4264
4265 /*
4266  * The function below are the high level ones.
4267  * only those ones must be called from the spoolss code.
4268  * JFM.
4269  */
4270
4271 /****************************************************************************
4272  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4273 ****************************************************************************/
4274
4275 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4276 {
4277         WERROR result;
4278
4279         dump_a_printer(printer, level);
4280
4281         switch (level) {
4282                 case 2:
4283                 {
4284                         /*
4285                          * Update the changestamp.  Emperical tests show that the
4286                          * ChangeID is always updated,but c_setprinter is
4287                          *  global spooler variable (not per printer).
4288                          */
4289
4290                         /* ChangeID **must** be increasing over the lifetime
4291                            of client's spoolss service in order for the
4292                            client's cache to show updates */
4293
4294                         printer->info_2->changeid = rev_changeid();
4295
4296                         /*
4297                          * Because one day someone will ask:
4298                          * NT->NT       An admin connection to a remote
4299                          *              printer show changes imeediately in
4300                          *              the properities dialog
4301                          *
4302                          *              A non-admin connection will only show the
4303                          *              changes after viewing the properites page
4304                          *              2 times.  Seems to be related to a
4305                          *              race condition in the client between the spooler
4306                          *              updating the local cache and the Explorer.exe GUI
4307                          *              actually displaying the properties.
4308                          *
4309                          *              This is fixed in Win2k.  admin/non-admin
4310                          *              connections both display changes immediately.
4311                          *
4312                          * 14/12/01     --jerry
4313                          */
4314
4315                         result=update_a_printer_2(printer->info_2);
4316                         break;
4317                 }
4318                 default:
4319                         result=WERR_UNKNOWN_LEVEL;
4320                         break;
4321         }
4322
4323         return result;
4324 }
4325
4326 /****************************************************************************
4327  Initialize printer devmode & data with previously saved driver init values.
4328 ****************************************************************************/
4329
4330 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4331 {
4332         int                     len = 0;
4333         char *key = NULL;
4334         TDB_DATA                dbuf;
4335         NT_PRINTER_INFO_LEVEL_2 info;
4336
4337
4338         ZERO_STRUCT(info);
4339
4340         /*
4341          * Delete any printer data 'values' already set. When called for driver
4342          * replace, there will generally be some, but during an add printer, there
4343          * should not be any (if there are delete them).
4344          */
4345
4346         if ( info_ptr->data )
4347                 delete_all_printer_data( info_ptr, "" );
4348
4349         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4350                                 info_ptr->drivername) < 0) {
4351                 return false;
4352         }
4353
4354         dbuf = tdb_fetch_bystring(tdb_drivers, key);
4355         if (!dbuf.dptr) {
4356                 /*
4357                  * When changing to a driver that has no init info in the tdb, remove
4358                  * the previous drivers init info and leave the new on blank.
4359                  */
4360                 free_nt_devicemode(&info_ptr->devmode);
4361                 SAFE_FREE(key);
4362                 return false;
4363         }
4364
4365         SAFE_FREE(key);
4366         /*
4367          * Get the saved DEVMODE..
4368          */
4369
4370         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4371
4372         /*
4373          * The saved DEVMODE contains the devicename from the printer used during
4374          * the initialization save. Change it to reflect the new printer.
4375          */
4376
4377         if ( info.devmode ) {
4378                 ZERO_STRUCT(info.devmode->devicename);
4379                 fstrcpy(info.devmode->devicename, info_ptr->printername);
4380         }
4381
4382         /*
4383          * NT/2k does not change out the entire DeviceMode of a printer
4384          * when changing the driver.  Only the driverextra, private, &
4385          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
4386          *
4387          * Later examination revealed that Windows NT/2k does reset the
4388          * the printer's device mode, bit **only** when you change a
4389          * property of the device mode such as the page orientation.
4390          * --jerry
4391          */
4392
4393
4394         /* Bind the saved DEVMODE to the new the printer */
4395
4396         free_nt_devicemode(&info_ptr->devmode);
4397         info_ptr->devmode = info.devmode;
4398
4399         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4400                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4401
4402         /* Add the printer data 'values' to the new printer */
4403
4404         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4405                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4406                 return False;
4407         }
4408
4409         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4410
4411         SAFE_FREE(dbuf.dptr);
4412
4413         return true;
4414 }
4415
4416 /****************************************************************************
4417  Initialize printer devmode & data with previously saved driver init values.
4418  When a printer is created using AddPrinter, the drivername bound to the
4419  printer is used to lookup previously saved driver initialization info, which
4420  is bound to the new printer.
4421 ****************************************************************************/
4422
4423 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4424 {
4425         bool result = False;
4426
4427         switch (level) {
4428                 case 2:
4429                         result = set_driver_init_2(printer->info_2);
4430                         break;
4431
4432                 default:
4433                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4434                                 level));
4435                         break;
4436         }
4437
4438         return result;
4439 }
4440
4441 /****************************************************************************
4442  Delete driver init data stored for a specified driver
4443 ****************************************************************************/
4444
4445 bool del_driver_init(const char *drivername)
4446 {
4447         char *key;
4448         bool ret;
4449
4450         if (!drivername || !*drivername) {
4451                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4452                 return false;
4453         }
4454
4455         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4456                 return false;
4457         }
4458
4459         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4460                                 drivername));
4461
4462         ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4463         SAFE_FREE(key);
4464         return ret;
4465 }
4466
4467 /****************************************************************************
4468  Pack up the DEVMODE and values for a printer into a 'driver init' entry
4469  in the tdb. Note: this is different from the driver entry and the printer
4470  entry. There should be a single driver init entry for each driver regardless
4471  of whether it was installed from NT or 2K. Technically, they should be
4472  different, but they work out to the same struct.
4473 ****************************************************************************/
4474
4475 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4476 {
4477         char *key = NULL;
4478         uint8 *buf;
4479         int buflen, len, ret;
4480         int retlen;
4481         TDB_DATA dbuf;
4482
4483         buf = NULL;
4484         buflen = 0;
4485
4486  again:
4487         len = 0;
4488         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4489
4490         retlen = pack_values( info->data, buf+len, buflen-len );
4491         if (retlen == -1) {
4492                 ret = -1;
4493                 goto done;
4494         }
4495         len += retlen;
4496
4497         if (buflen < len) {
4498                 buf = (uint8 *)SMB_REALLOC(buf, len);
4499                 if (!buf) {
4500                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4501                         ret = -1;
4502                         goto done;
4503                 }
4504                 buflen = len;
4505                 goto again;
4506         }
4507
4508         SAFE_FREE(key);
4509         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4510                 ret = (uint32)-1;
4511                 goto done;
4512         }
4513
4514         dbuf.dptr = buf;
4515         dbuf.dsize = len;
4516
4517         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4518
4519 done:
4520         if (ret == -1)
4521                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4522
4523         SAFE_FREE(buf);
4524
4525         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4526                  info->sharename, info->drivername));
4527
4528         return ret;
4529 }
4530
4531 /****************************************************************************
4532  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4533 ****************************************************************************/
4534
4535 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4536 {
4537         uint32 result;
4538
4539         dump_a_printer(printer, level);
4540
4541         switch (level) {
4542                 case 2:
4543                         result = update_driver_init_2(printer->info_2);
4544                         break;
4545                 default:
4546                         result = 1;
4547                         break;
4548         }
4549
4550         return result;
4551 }
4552
4553 /****************************************************************************
4554  Convert the printer data value, a REG_BINARY array, into an initialization
4555  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4556  got to keep the endians happy :).
4557 ****************************************************************************/
4558
4559 static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
4560                                 const uint8_t *data, uint32_t data_len)
4561 {
4562         struct spoolss_DeviceMode devmode;
4563         enum ndr_err_code ndr_err;
4564         DATA_BLOB blob;
4565
4566         ZERO_STRUCT(devmode);
4567
4568         blob = data_blob_const(data, data_len);
4569
4570         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
4571                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4572         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4573                 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4574                 return false;
4575         }
4576
4577         return convert_devicemode("", &devmode, &nt_devmode);
4578 }
4579
4580 /****************************************************************************
4581  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4582
4583  1. Use the driver's config DLL to this UNC printername and:
4584     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4585     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4586  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4587
4588  The last step triggers saving the "driver initialization" information for
4589  this printer into the tdb. Later, new printers that use this driver will
4590  have this initialization information bound to them. This simulates the
4591  driver initialization, as if it had run on the Samba server (as it would
4592  have done on NT).
4593
4594  The Win32 client side code requirement sucks! But until we can run arbitrary
4595  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4596
4597  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4598  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4599  about it and you will realize why.  JRR 010720
4600 ****************************************************************************/
4601
4602 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4603 {
4604         WERROR        status       = WERR_OK;
4605         TALLOC_CTX    *ctx         = NULL;
4606         NT_DEVICEMODE *nt_devmode  = NULL;
4607         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4608
4609         /*
4610          * When the DEVMODE is already set on the printer, don't try to unpack it.
4611          */
4612         DEBUG(8,("save_driver_init_2: Enter...\n"));
4613
4614         if ( !printer->info_2->devmode && data_len ) {
4615                 /*
4616                  * Set devmode on printer info, so entire printer initialization can be
4617                  * saved to tdb.
4618                  */
4619
4620                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4621                         return WERR_NOMEM;
4622
4623                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4624                         status = WERR_NOMEM;
4625                         goto done;
4626                 }
4627
4628                 ZERO_STRUCTP(nt_devmode);
4629
4630                 /*
4631                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4632                  * Convert it to to a devmode structure
4633                  */
4634                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4635                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4636                         status = WERR_INVALID_PARAM;
4637                         goto done;
4638                 }
4639
4640                 printer->info_2->devmode = nt_devmode;
4641         }
4642
4643         /*
4644          * Pack up and add (or update) the DEVMODE and any current printer data to
4645          * a 'driver init' element in the tdb
4646          *
4647          */
4648
4649         if ( update_driver_init(printer, 2) != 0 ) {
4650                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4651                 status = WERR_NOMEM;
4652                 goto done;
4653         }
4654
4655         /*
4656          * If driver initialization info was successfully saved, set the current
4657          * printer to match it. This allows initialization of the current printer
4658          * as well as the driver.
4659          */
4660         status = mod_a_printer(printer, 2);
4661         if (!W_ERROR_IS_OK(status)) {
4662                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4663                                   printer->info_2->printername));
4664         }
4665
4666   done:
4667         talloc_destroy(ctx);
4668         free_nt_devicemode( &nt_devmode );
4669
4670         printer->info_2->devmode = tmp_devmode;
4671
4672         return status;
4673 }
4674
4675 /****************************************************************************
4676  Update the driver init info (DEVMODE and specifics) for a printer
4677 ****************************************************************************/
4678
4679 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4680 {
4681         WERROR status = WERR_OK;
4682
4683         switch (level) {
4684                 case 2:
4685                         status = save_driver_init_2( printer, data, data_len );
4686                         break;
4687                 default:
4688                         status = WERR_UNKNOWN_LEVEL;
4689                         break;
4690         }
4691
4692         return status;
4693 }
4694
4695 /****************************************************************************
4696  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4697
4698  Previously the code had a memory allocation problem because it always
4699  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4700  as a long as the original handle is open.  So if the client made a lot
4701  of getprinter[data]() calls, the memory usage would climb.  Now we use
4702  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4703  still use the Printer_entry->ctx for maintaining the cache copy though
4704  since that object must live as long as the handle by definition.
4705                                                     --jerry
4706
4707 ****************************************************************************/
4708
4709 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4710                         const char *sharename, bool get_loc_com)
4711 {
4712         WERROR result;
4713         fstring servername;
4714
4715         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4716
4717         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4718                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4719                 return WERR_NOMEM;
4720         }
4721
4722         switch (level) {
4723                 case 2:
4724                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4725                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4726                                 TALLOC_FREE( *pp_printer );
4727                                 return WERR_NOMEM;
4728                         }
4729
4730                         if ( print_hnd )
4731                                 fstrcpy( servername, print_hnd->servername );
4732                         else {
4733                                 fstrcpy( servername, "%L" );
4734                                 standard_sub_basic( "", "", servername,
4735                                                     sizeof(servername)-1 );
4736                         }
4737
4738                         result = get_a_printer_2( (*pp_printer)->info_2,
4739                                         servername, sharename, get_loc_com);
4740
4741                         /* we have a new printer now.  Save it with this handle */
4742
4743                         if ( !W_ERROR_IS_OK(result) ) {
4744                                 TALLOC_FREE( *pp_printer );
4745                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4746                                         sharename, (unsigned int)level, win_errstr(result)));
4747                                 return result;
4748                         }
4749
4750                         dump_a_printer( *pp_printer, level);
4751
4752                         break;
4753
4754                 default:
4755                         TALLOC_FREE( *pp_printer );
4756                         return WERR_UNKNOWN_LEVEL;
4757         }
4758
4759         return WERR_OK;
4760 }
4761
4762 WERROR get_a_printer( Printer_entry *print_hnd,
4763                         NT_PRINTER_INFO_LEVEL **pp_printer,
4764                         uint32 level,
4765                         const char *sharename)
4766 {
4767         return get_a_printer_internal(print_hnd, pp_printer, level,
4768                                         sharename, true);
4769 }
4770
4771 WERROR get_a_printer_search( Printer_entry *print_hnd,
4772                         NT_PRINTER_INFO_LEVEL **pp_printer,
4773                         uint32 level,
4774                         const char *sharename)
4775 {
4776         return get_a_printer_internal(print_hnd, pp_printer, level,
4777                                         sharename, false);
4778 }
4779
4780 /****************************************************************************
4781  Deletes a NT_PRINTER_INFO_LEVEL struct.
4782 ****************************************************************************/
4783
4784 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4785 {
4786         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4787
4788         if ( !printer )
4789                 return 0;
4790
4791         switch (level) {
4792                 case 2:
4793                         if ( printer->info_2 )
4794                                 free_nt_printer_info_level_2(&printer->info_2);
4795                         break;
4796
4797                 default:
4798                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4799                         return 1;
4800         }
4801
4802         TALLOC_FREE(*pp_printer);
4803
4804         return 0;
4805 }
4806
4807 /****************************************************************************
4808 ****************************************************************************/
4809 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4810 {
4811         uint32 result;
4812         DEBUG(104,("adding a printer at level [%d]\n", level));
4813         dump_a_printer_driver(driver, level);
4814
4815         switch (level) {
4816                 case 3:
4817                         result=add_a_printer_driver_3(driver.info_3);
4818                         break;
4819
4820                 case 6:
4821                         result=add_a_printer_driver_6(driver.info_6);
4822                         break;
4823
4824                 default:
4825                         result=1;
4826                         break;
4827         }
4828
4829         return result;
4830 }
4831 /****************************************************************************
4832 ****************************************************************************/
4833
4834 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
4835                             const char *drivername, const char *architecture,
4836                             uint32_t version)
4837 {
4838         WERROR result;
4839
4840         switch (level) {
4841                 case 3:
4842                         /* Sometime we just want any version of the driver */
4843
4844                         if ( version == DRIVER_ANY_VERSION ) {
4845                                 /* look for Win2k first and then for NT4 */
4846                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4847                                                 architecture, 3);
4848
4849                                 if ( !W_ERROR_IS_OK(result) ) {
4850                                         result = get_a_printer_driver_3( &driver->info_3,
4851                                                         drivername, architecture, 2 );
4852                                 }
4853                         } else {
4854                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4855                                         architecture, version);
4856                         }
4857                         break;
4858
4859                 default:
4860                         result=W_ERROR(1);
4861                         break;
4862         }
4863
4864         if (W_ERROR_IS_OK(result))
4865                 dump_a_printer_driver(*driver, level);
4866
4867         return result;
4868 }
4869
4870 /****************************************************************************
4871 ****************************************************************************/
4872 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4873 {
4874         uint32 result;
4875
4876         switch (level) {
4877                 case 3:
4878                 {
4879                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4880                         if (driver.info_3 != NULL)
4881                         {
4882                                 info3=driver.info_3;
4883                                 SAFE_FREE(info3->dependentfiles);
4884                                 ZERO_STRUCTP(info3);
4885                                 SAFE_FREE(info3);
4886                                 result=0;
4887                         } else {
4888                                 result=4;
4889                         }
4890                         break;
4891                 }
4892                 case 6:
4893                 {
4894                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4895                         if (driver.info_6 != NULL) {
4896                                 info6=driver.info_6;
4897                                 SAFE_FREE(info6->dependentfiles);
4898                                 SAFE_FREE(info6->previousnames);
4899                                 ZERO_STRUCTP(info6);
4900                                 SAFE_FREE(info6);
4901                                 result=0;
4902                         } else {
4903                                 result=4;
4904                         }
4905                         break;
4906                 }
4907                 default:
4908                         result=1;
4909                         break;
4910         }
4911         return result;
4912 }
4913
4914
4915 /****************************************************************************
4916   Determine whether or not a particular driver is currently assigned
4917   to a printer
4918 ****************************************************************************/
4919
4920 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4921 {
4922         int snum;
4923         int n_services = lp_numservices();
4924         NT_PRINTER_INFO_LEVEL *printer = NULL;
4925         bool in_use = False;
4926
4927         if ( !info_3 )
4928                 return False;
4929
4930         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4931
4932         /* loop through the printers.tdb and check for the drivername */
4933
4934         for (snum=0; snum<n_services && !in_use; snum++) {
4935                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4936                         continue;
4937
4938                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4939                         continue;
4940
4941                 if ( strequal(info_3->name, printer->info_2->drivername) )
4942                         in_use = True;
4943
4944                 free_a_printer( &printer, 2 );
4945         }
4946
4947         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4948
4949         if ( in_use ) {
4950                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4951                 WERROR werr;
4952
4953                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4954
4955                 /* we can still remove the driver if there is one of
4956                    "Windows NT x86" version 2 or 3 left */
4957
4958                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4959                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4960                 }
4961                 else {
4962                         switch ( info_3->cversion ) {
4963                         case 2:
4964                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4965                                 break;
4966                         case 3:
4967                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4968                                 break;
4969                         default:
4970                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4971                                         info_3->cversion));
4972                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4973                                 break;
4974                         }
4975                 }
4976
4977                 /* now check the error code */
4978
4979                 if ( W_ERROR_IS_OK(werr) ) {
4980                         /* it's ok to remove the driver, we have other architctures left */
4981                         in_use = False;
4982                         free_a_printer_driver( d, 3 );
4983                 }
4984         }
4985
4986         /* report that the driver is not in use by default */
4987
4988         return in_use;
4989 }
4990
4991
4992 /**********************************************************************
4993  Check to see if a ogiven file is in use by *info
4994  *********************************************************************/
4995
4996 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4997 {
4998         int i = 0;
4999
5000         if ( !info )
5001                 return False;
5002
5003         /* mz: skip files that are in the list but already deleted */
5004         if (!file || !file[0]) {
5005                 return false;
5006         }
5007
5008         if ( strequal(file, info->driverpath) )
5009                 return True;
5010
5011         if ( strequal(file, info->datafile) )
5012                 return True;
5013
5014         if ( strequal(file, info->configfile) )
5015                 return True;
5016
5017         if ( strequal(file, info->helpfile) )
5018                 return True;
5019
5020         /* see of there are any dependent files to examine */
5021
5022         if ( !info->dependentfiles )
5023                 return False;
5024
5025         while ( *info->dependentfiles[i] ) {
5026                 if ( strequal(file, info->dependentfiles[i]) )
5027                         return True;
5028                 i++;
5029         }
5030
5031         return False;
5032
5033 }
5034
5035 /**********************************************************************
5036  Utility function to remove the dependent file pointed to by the
5037  input parameter from the list
5038  *********************************************************************/
5039
5040 static void trim_dependent_file( fstring files[], int idx )
5041 {
5042
5043         /* bump everything down a slot */
5044
5045         while( *files[idx+1] ) {
5046                 fstrcpy( files[idx], files[idx+1] );
5047                 idx++;
5048         }
5049
5050         *files[idx] = '\0';
5051
5052         return;
5053 }
5054
5055 /**********************************************************************
5056  Check if any of the files used by src are also used by drv
5057  *********************************************************************/
5058
5059 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
5060                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
5061 {
5062         bool    in_use = False;
5063         int     i = 0;
5064
5065         if ( !src || !drv )
5066                 return False;
5067
5068         /* check each file.  Remove it from the src structure if it overlaps */
5069
5070         if ( drv_file_in_use(src->driverpath, drv) ) {
5071                 in_use = True;
5072                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
5073                 fstrcpy( src->driverpath, "" );
5074         }
5075
5076         if ( drv_file_in_use(src->datafile, drv) ) {
5077                 in_use = True;
5078                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
5079                 fstrcpy( src->datafile, "" );
5080         }
5081
5082         if ( drv_file_in_use(src->configfile, drv) ) {
5083                 in_use = True;
5084                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5085                 fstrcpy( src->configfile, "" );
5086         }
5087
5088         if ( drv_file_in_use(src->helpfile, drv) ) {
5089                 in_use = True;
5090                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5091                 fstrcpy( src->helpfile, "" );
5092         }
5093
5094         /* are there any dependentfiles to examine? */
5095
5096         if ( !src->dependentfiles )
5097                 return in_use;
5098
5099         while ( *src->dependentfiles[i] ) {
5100                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5101                         in_use = True;
5102                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5103                         trim_dependent_file( src->dependentfiles, i );
5104                 } else
5105                         i++;
5106         }
5107
5108         return in_use;
5109 }
5110
5111 /****************************************************************************
5112   Determine whether or not a particular driver files are currently being
5113   used by any other driver.
5114
5115   Return value is True if any files were in use by other drivers
5116   and False otherwise.
5117
5118   Upon return, *info has been modified to only contain the driver files
5119   which are not in use
5120
5121   Fix from mz:
5122
5123   This needs to check all drivers to ensure that all files in use
5124   have been removed from *info, not just the ones in the first
5125   match.
5126 ****************************************************************************/
5127
5128 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5129 {
5130         int                             i;
5131         int                             ndrivers;
5132         uint32                          version;
5133         fstring                         *list = NULL;
5134         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5135         bool in_use = false;
5136
5137         if ( !info )
5138                 return False;
5139
5140         version = info->cversion;
5141
5142         /* loop over all driver versions */
5143
5144         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5145
5146         /* get the list of drivers */
5147
5148         list = NULL;
5149         ndrivers = get_ntdrivers(&list, info->environment, version);
5150
5151         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5152                 ndrivers, info->environment, version));
5153
5154         /* check each driver for overlap in files */
5155
5156         for (i=0; i<ndrivers; i++) {
5157                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5158
5159                 ZERO_STRUCT(driver);
5160
5161                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5162                         SAFE_FREE(list);
5163                         return True;
5164                 }
5165
5166                 /* check if d2 uses any files from d1 */
5167                 /* only if this is a different driver than the one being deleted */
5168
5169                 if ( !strequal(info->name, driver.info_3->name) ) {
5170                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
5171                                 /* mz: Do not instantly return -
5172                                  * we need to ensure this file isn't
5173                                  * also in use by other drivers. */
5174                                 in_use = true;
5175                         }
5176                 }
5177
5178                 free_a_printer_driver(driver, 3);
5179         }
5180
5181         SAFE_FREE(list);
5182
5183         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5184
5185         driver.info_3 = info;
5186
5187         if ( DEBUGLEVEL >= 20 )
5188                 dump_a_printer_driver( driver, 3 );
5189
5190         return in_use;
5191 }
5192
5193 /****************************************************************************
5194   Actually delete the driver files.  Make sure that
5195   printer_driver_files_in_use() return False before calling
5196   this.
5197 ****************************************************************************/
5198
5199 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5200                                 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
5201 {
5202         int i = 0;
5203         char *s;
5204         const char *file;
5205         connection_struct *conn;
5206         NTSTATUS nt_status;
5207         SMB_STRUCT_STAT  st;
5208         char *oldcwd;
5209         fstring printdollar;
5210         int printdollar_snum;
5211         bool ret = false;
5212
5213         if ( !info_3 )
5214                 return False;
5215
5216         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5217
5218         fstrcpy(printdollar, "print$");
5219
5220         printdollar_snum = find_service(printdollar);
5221         if (printdollar_snum == -1) {
5222                 return false;
5223         }
5224
5225         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5226                                        lp_pathname(printdollar_snum),
5227                                        rpc_pipe->server_info, &oldcwd);
5228         if (!NT_STATUS_IS_OK(nt_status)) {
5229                 DEBUG(0,("delete_driver_files: create_conn_struct "
5230                          "returned %s\n", nt_errstr(nt_status)));
5231                 return false;
5232         }
5233
5234         if ( !CAN_WRITE(conn) ) {
5235                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5236                 goto fail;
5237         }
5238
5239         /* now delete the files; must strip the '\print$' string from
5240            fron of path                                                */
5241
5242         if ( *info_3->driverpath ) {
5243                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5244                         file = s;
5245                         driver_unix_convert(conn,file,&st);
5246                         DEBUG(10,("deleting driverfile [%s]\n", s));
5247                         unlink_internals(conn, NULL, 0, file, False);
5248                 }
5249         }
5250
5251         if ( *info_3->configfile ) {
5252                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5253                         file = s;
5254                         driver_unix_convert(conn,file,&st);
5255                         DEBUG(10,("deleting configfile [%s]\n", s));
5256                         unlink_internals(conn, NULL, 0, file, False);
5257                 }
5258         }
5259
5260         if ( *info_3->datafile ) {
5261                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5262                         file = s;
5263                         driver_unix_convert(conn,file,&st);
5264                         DEBUG(10,("deleting datafile [%s]\n", s));
5265                         unlink_internals(conn, NULL, 0, file, False);
5266                 }
5267         }
5268
5269         if ( *info_3->helpfile ) {
5270                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5271                         file = s;
5272                         driver_unix_convert(conn,file,&st);
5273                         DEBUG(10,("deleting helpfile [%s]\n", s));
5274                         unlink_internals(conn, NULL, 0, file, False);
5275                 }
5276         }
5277
5278         /* check if we are done removing files */
5279
5280         if ( info_3->dependentfiles ) {
5281                 while ( info_3->dependentfiles[i][0] ) {
5282                         char *p;
5283
5284                         /* bypass the "\print$" portion of the path */
5285
5286                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5287                                 file = p;
5288                                 driver_unix_convert(conn,file,&st);
5289                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5290                                 unlink_internals(conn, NULL, 0, file, False);
5291                         }
5292
5293                         i++;
5294                 }
5295         }
5296
5297         goto done;
5298  fail:
5299         ret = false;
5300  done:
5301         if (conn != NULL) {
5302                 vfs_ChDir(conn, oldcwd);
5303                 conn_free_internal(conn);
5304         }
5305         return ret;
5306 }
5307
5308 /****************************************************************************
5309  Remove a printer driver from the TDB.  This assumes that the the driver was
5310  previously looked up.
5311  ***************************************************************************/
5312
5313 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5314                              NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3,
5315                              uint32 version, bool delete_files )
5316 {
5317         char *key = NULL;
5318         const char     *arch;
5319         TDB_DATA        dbuf;
5320         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
5321
5322         /* delete the tdb data first */
5323
5324         arch = get_short_archi(info_3->environment);
5325         if (!arch) {
5326                 return WERR_UNKNOWN_PRINTER_DRIVER;
5327         }
5328         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5329                         arch, version, info_3->name) < 0) {
5330                 return WERR_NOMEM;
5331         }
5332
5333         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5334                 key, delete_files ? "TRUE" : "FALSE" ));
5335
5336         ctr.info_3 = info_3;
5337         dump_a_printer_driver( ctr, 3 );
5338
5339         /* check if the driver actually exists for this environment */
5340
5341         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5342         if ( !dbuf.dptr ) {
5343                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5344                 SAFE_FREE(key);
5345                 return WERR_UNKNOWN_PRINTER_DRIVER;
5346         }
5347
5348         SAFE_FREE( dbuf.dptr );
5349
5350         /* ok... the driver exists so the delete should return success */
5351
5352         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5353                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5354                 SAFE_FREE(key);
5355                 return WERR_ACCESS_DENIED;
5356         }
5357
5358         /*
5359          * now delete any associated files if delete_files == True
5360          * even if this part failes, we return succes because the
5361          * driver doesn not exist any more
5362          */
5363
5364         if ( delete_files )
5365                 delete_driver_files(rpc_pipe, info_3);
5366
5367         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5368         SAFE_FREE(key);
5369
5370         return WERR_OK;
5371 }
5372
5373 /****************************************************************************
5374  Store a security desc for a printer.
5375 ****************************************************************************/
5376
5377 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5378 {
5379         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5380         SEC_DESC_BUF *old_secdesc_ctr = NULL;
5381         TALLOC_CTX *mem_ctx = NULL;
5382         TDB_DATA kbuf;
5383         TDB_DATA dbuf;
5384         DATA_BLOB blob;
5385         WERROR status;
5386         NTSTATUS nt_status;
5387
5388         mem_ctx = talloc_init("nt_printing_setsec");
5389         if (mem_ctx == NULL)
5390                 return WERR_NOMEM;
5391
5392         /* The old owner and group sids of the security descriptor are not
5393            present when new ACEs are added or removed by changing printer
5394            permissions through NT.  If they are NULL in the new security
5395            descriptor then copy them over from the old one. */
5396
5397         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5398                 DOM_SID *owner_sid, *group_sid;
5399                 SEC_ACL *dacl, *sacl;
5400                 SEC_DESC *psd = NULL;
5401                 size_t size;
5402
5403                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5404                         status = WERR_NOMEM;
5405                         goto out;
5406                 }
5407
5408                 /* Pick out correct owner and group sids */
5409
5410                 owner_sid = secdesc_ctr->sd->owner_sid ?
5411                         secdesc_ctr->sd->owner_sid :
5412                         old_secdesc_ctr->sd->owner_sid;
5413
5414                 group_sid = secdesc_ctr->sd->group_sid ?
5415                         secdesc_ctr->sd->group_sid :
5416                         old_secdesc_ctr->sd->group_sid;
5417
5418                 dacl = secdesc_ctr->sd->dacl ?
5419                         secdesc_ctr->sd->dacl :
5420                         old_secdesc_ctr->sd->dacl;
5421
5422                 sacl = secdesc_ctr->sd->sacl ?
5423                         secdesc_ctr->sd->sacl :
5424                         old_secdesc_ctr->sd->sacl;
5425
5426                 /* Make a deep copy of the security descriptor */
5427
5428                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5429                                     owner_sid, group_sid,
5430                                     sacl,
5431                                     dacl,
5432                                     &size);
5433
5434                 if (!psd) {
5435                         status = WERR_NOMEM;
5436                         goto out;
5437                 }
5438
5439                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5440         }
5441
5442         if (!new_secdesc_ctr) {
5443                 new_secdesc_ctr = secdesc_ctr;
5444         }
5445
5446         /* Store the security descriptor in a tdb */
5447
5448         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5449                                           &blob.data, &blob.length);
5450         if (!NT_STATUS_IS_OK(nt_status)) {
5451                 status = ntstatus_to_werror(nt_status);
5452                 goto out;
5453         }
5454
5455         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5456
5457         dbuf.dptr = (unsigned char *)blob.data;
5458         dbuf.dsize = blob.length;
5459
5460         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5461                 status = WERR_OK;
5462         } else {
5463                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5464                 status = WERR_BADFUNC;
5465         }
5466
5467         /* Free malloc'ed memory */
5468         talloc_free(blob.data);
5469
5470  out:
5471
5472         if (mem_ctx)
5473                 talloc_destroy(mem_ctx);
5474         return status;
5475 }
5476
5477 /****************************************************************************
5478  Construct a default security descriptor buffer for a printer.
5479 ****************************************************************************/
5480
5481 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5482 {
5483         SEC_ACE ace[5]; /* max number of ace entries */
5484         int i = 0;
5485         uint32_t sa;
5486         SEC_ACL *psa = NULL;
5487         SEC_DESC_BUF *sdb = NULL;
5488         SEC_DESC *psd = NULL;
5489         DOM_SID adm_sid;
5490         size_t sd_size;
5491
5492         /* Create an ACE where Everyone is allowed to print */
5493
5494         sa = PRINTER_ACE_PRINT;
5495         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5496                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5497
5498         /* Add the domain admins group if we are a DC */
5499
5500         if ( IS_DC ) {
5501                 DOM_SID domadmins_sid;
5502
5503                 sid_copy(&domadmins_sid, get_global_sam_sid());
5504                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5505
5506                 sa = PRINTER_ACE_FULL_CONTROL;
5507                 init_sec_ace(&ace[i++], &domadmins_sid,
5508                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5509                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5510                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5511                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5512         }
5513         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5514                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5515
5516                 sa = PRINTER_ACE_FULL_CONTROL;
5517                 init_sec_ace(&ace[i++], &adm_sid,
5518                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5519                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5520                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5521                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5522         }
5523
5524         /* add BUILTIN\Administrators as FULL CONTROL */
5525
5526         sa = PRINTER_ACE_FULL_CONTROL;
5527         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5528                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5529                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5530         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5531                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5532                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5533
5534         /* Make the security descriptor owned by the BUILTIN\Administrators */
5535
5536         /* The ACL revision number in rpc_secdesc.h differs from the one
5537            created by NT when setting ACE entries in printer
5538            descriptors.  NT4 complains about the property being edited by a
5539            NT5 machine. */
5540
5541         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5542                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5543                         &global_sid_Builtin_Administrators,
5544                         &global_sid_Builtin_Administrators,
5545                         NULL, psa, &sd_size);
5546         }
5547
5548         if (!psd) {
5549                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5550                 return NULL;
5551         }
5552
5553         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5554
5555         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5556                  (unsigned int)sd_size));
5557
5558         return sdb;
5559 }
5560
5561 /****************************************************************************
5562  Get a security desc for a printer.
5563 ****************************************************************************/
5564
5565 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5566 {
5567         TDB_DATA kbuf;
5568         TDB_DATA dbuf;
5569         DATA_BLOB blob;
5570         char *temp;
5571         NTSTATUS status;
5572
5573         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5574                 sharename = temp + 1;
5575         }
5576
5577         /* Fetch security descriptor from tdb */
5578
5579         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5580
5581         dbuf = tdb_fetch(tdb_printers, kbuf);
5582         if (dbuf.dptr) {
5583
5584                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5585                                                  secdesc_ctr);
5586                 SAFE_FREE(dbuf.dptr);
5587
5588                 if (NT_STATUS_IS_OK(status)) {
5589                         return true;
5590                 }
5591         }
5592
5593         *secdesc_ctr = construct_default_printer_sdb(ctx);
5594         if (!*secdesc_ctr) {
5595                 return false;
5596         }
5597
5598         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5599                                        &blob.data, &blob.length);
5600         if (NT_STATUS_IS_OK(status)) {
5601                 dbuf.dptr = (unsigned char *)blob.data;
5602                 dbuf.dsize = blob.length;
5603                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5604                 talloc_free(blob.data);
5605         }
5606
5607         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5608            this security descriptor has been created when winbindd was
5609            down.  Take ownership of security descriptor. */
5610
5611         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5612                 DOM_SID owner_sid;
5613
5614                 /* Change sd owner to workgroup administrator */
5615
5616                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5617                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5618                         SEC_DESC *psd = NULL;
5619                         size_t size;
5620
5621                         /* Create new sd */
5622
5623                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5624
5625                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5626                                             &owner_sid,
5627                                             (*secdesc_ctr)->sd->group_sid,
5628                                             (*secdesc_ctr)->sd->sacl,
5629                                             (*secdesc_ctr)->sd->dacl,
5630                                             &size);
5631
5632                         if (!psd) {
5633                                 return False;
5634                         }
5635
5636                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5637                         if (!new_secdesc_ctr) {
5638                                 return False;
5639                         }
5640
5641                         /* Swap with other one */
5642
5643                         *secdesc_ctr = new_secdesc_ctr;
5644
5645                         /* Set it */
5646
5647                         nt_printing_setsec(sharename, *secdesc_ctr);
5648                 }
5649         }
5650
5651         if (DEBUGLEVEL >= 10) {
5652                 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5653                 int i;
5654
5655                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5656                            sharename, the_acl->num_aces));
5657
5658                 for (i = 0; i < the_acl->num_aces; i++) {
5659                         DEBUG(10, ("%s %d %d 0x%08x\n",
5660                                    sid_string_dbg(&the_acl->aces[i].trustee),
5661                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5662                                    the_acl->aces[i].access_mask));
5663                 }
5664         }
5665
5666         return True;
5667 }
5668
5669 /* error code:
5670         0: everything OK
5671         1: level not implemented
5672         2: file doesn't exist
5673         3: can't allocate memory
5674         4: can't free memory
5675         5: non existant struct
5676 */
5677
5678 /*
5679         A printer and a printer driver are 2 different things.
5680         NT manages them separatelly, Samba does the same.
5681         Why ? Simply because it's easier and it makes sense !
5682
5683         Now explanation: You have 3 printers behind your samba server,
5684         2 of them are the same make and model (laser A and B). But laser B
5685         has an 3000 sheet feeder and laser A doesn't such an option.
5686         Your third printer is an old dot-matrix model for the accounting :-).
5687
5688         If the /usr/local/samba/lib directory (default dir), you will have
5689         5 files to describe all of this.
5690
5691         3 files for the printers (1 by printer):
5692                 NTprinter_laser A
5693                 NTprinter_laser B
5694                 NTprinter_accounting
5695         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5696                 NTdriver_printer model X
5697                 NTdriver_printer model Y
5698
5699 jfm: I should use this comment for the text file to explain
5700         same thing for the forms BTW.
5701         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5702
5703 */
5704
5705 /* Convert generic access rights to printer object specific access rights.
5706    It turns out that NT4 security descriptors use generic access rights and
5707    NT5 the object specific ones. */
5708
5709 void map_printer_permissions(SEC_DESC *sd)
5710 {
5711         int i;
5712
5713         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5714                 se_map_generic(&sd->dacl->aces[i].access_mask,
5715                                &printer_generic_mapping);
5716         }
5717 }
5718
5719 void map_job_permissions(SEC_DESC *sd)
5720 {
5721         int i;
5722
5723         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5724                 se_map_generic(&sd->dacl->aces[i].access_mask,
5725                                &job_generic_mapping);
5726         }
5727 }
5728
5729
5730 /****************************************************************************
5731  Check a user has permissions to perform the given operation.  We use the
5732  permission constants defined in include/rpc_spoolss.h to check the various
5733  actions we perform when checking printer access.
5734
5735    PRINTER_ACCESS_ADMINISTER:
5736        print_queue_pause, print_queue_resume, update_printer_sec,
5737        update_printer, spoolss_addprinterex_level_2,
5738        _spoolss_setprinterdata
5739
5740    PRINTER_ACCESS_USE:
5741        print_job_start
5742
5743    JOB_ACCESS_ADMINISTER:
5744        print_job_delete, print_job_pause, print_job_resume,
5745        print_queue_purge
5746
5747   Try access control in the following order (for performance reasons):
5748     1)  root ans SE_PRINT_OPERATOR can do anything (easy check)
5749     2)  check security descriptor (bit comparisons in memory)
5750     3)  "printer admins" (may result in numerous calls to winbind)
5751
5752  ****************************************************************************/
5753 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5754                         int access_type)
5755 {
5756         SEC_DESC_BUF *secdesc = NULL;
5757         uint32 access_granted;
5758         NTSTATUS status;
5759         const char *pname;
5760         TALLOC_CTX *mem_ctx = NULL;
5761         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5762
5763         /* If user is NULL then use the current_user structure */
5764
5765         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5766
5767         if (server_info->utok.uid == 0
5768             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5769                 return True;
5770         }
5771
5772         /* Get printer name */
5773
5774         pname = PRINTERNAME(snum);
5775
5776         if (!pname || !*pname) {
5777                 errno = EACCES;
5778                 return False;
5779         }
5780
5781         /* Get printer security descriptor */
5782
5783         if(!(mem_ctx = talloc_init("print_access_check"))) {
5784                 errno = ENOMEM;
5785                 return False;
5786         }
5787
5788         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5789                 talloc_destroy(mem_ctx);
5790                 errno = ENOMEM;
5791                 return False;
5792         }
5793
5794         if (access_type == JOB_ACCESS_ADMINISTER) {
5795                 SEC_DESC_BUF *parent_secdesc = secdesc;
5796
5797                 /* Create a child security descriptor to check permissions
5798                    against.  This is because print jobs are child objects
5799                    objects of a printer. */
5800
5801                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5802
5803                 if (!NT_STATUS_IS_OK(status)) {
5804                         talloc_destroy(mem_ctx);
5805                         errno = map_errno_from_nt_status(status);
5806                         return False;
5807                 }
5808
5809                 map_job_permissions(secdesc->sd);
5810         } else {
5811                 map_printer_permissions(secdesc->sd);
5812         }
5813
5814         /* Check access */
5815         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5816                                  &access_granted);
5817
5818         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5819
5820         /* see if we need to try the printer admin list */
5821
5822         if ((access_granted == 0) &&
5823             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5824                                          NULL, NULL, server_info->ptok,
5825                                          lp_printer_admin(snum)))) {
5826                 talloc_destroy(mem_ctx);
5827                 return True;
5828         }
5829
5830         talloc_destroy(mem_ctx);
5831
5832         if (!NT_STATUS_IS_OK(status)) {
5833                 errno = EACCES;
5834         }
5835
5836         return NT_STATUS_IS_OK(status);
5837 }
5838
5839 /****************************************************************************
5840  Check the time parameters allow a print operation.
5841 *****************************************************************************/
5842
5843 bool print_time_access_check(const char *servicename)
5844 {
5845         NT_PRINTER_INFO_LEVEL *printer = NULL;
5846         bool ok = False;
5847         time_t now = time(NULL);
5848         struct tm *t;
5849         uint32 mins;
5850
5851         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5852                 return False;
5853
5854         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5855                 ok = True;
5856
5857         t = gmtime(&now);
5858         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5859
5860         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5861                 ok = True;
5862
5863         free_a_printer(&printer, 2);
5864
5865         if (!ok)
5866                 errno = EACCES;
5867
5868         return ok;
5869 }
5870
5871 /****************************************************************************
5872  Fill in the servername sent in the _spoolss_open_printer_ex() call
5873 ****************************************************************************/
5874
5875 char* get_server_name( Printer_entry *printer )
5876 {
5877         return printer->servername;
5878 }
5879
5880