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