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