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