s3-printing: rework move_driver_file_to_download_area() a bit for clarity.
[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 *short_architecture,
1810                                                 uint32_t driver_version,
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         old_name = talloc_asprintf(mem_ctx, "%s/%s",
1819                                    short_architecture, driver_file);
1820         W_ERROR_HAVE_NO_MEMORY(old_name);
1821
1822         new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1823                                    short_architecture, driver_version, driver_file);
1824         W_ERROR_HAVE_NO_MEMORY(new_name);
1825
1826         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1827
1828                 old_name = driver_unix_convert(conn, old_name, &st);
1829                 W_ERROR_HAVE_NO_MEMORY(old_name);
1830
1831                 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to '%s'\n",
1832                         old_name, new_name));
1833
1834                 status = copy_file(mem_ctx, conn, old_name, new_name,
1835                                    OPENX_FILE_EXISTS_TRUNCATE |
1836                                    OPENX_FILE_CREATE_IF_NOT_EXIST,
1837                                    0, false);
1838
1839                 if (!NT_STATUS_IS_OK(status)) {
1840                         DEBUG(0,("move_driver_file_to_download_area: Unable to rename [%s] to [%s]: %s\n",
1841                                 old_name, new_name, nt_errstr(status)));
1842                         return WERR_ACCESS_DENIED;
1843                 }
1844         }
1845
1846         return WERR_OK;
1847 }
1848
1849 WERROR move_driver_to_download_area(struct pipes_struct *p,
1850                                     NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1851                                     uint32 level, WERROR *perr)
1852 {
1853         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1854         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1855         const char *short_architecture;
1856         char *new_dir = NULL;
1857         connection_struct *conn = NULL;
1858         NTSTATUS nt_status;
1859         SMB_STRUCT_STAT st;
1860         int i;
1861         TALLOC_CTX *ctx = talloc_tos();
1862         int ver = 0;
1863         char *oldcwd;
1864         fstring printdollar;
1865         int printdollar_snum;
1866
1867         *perr = WERR_OK;
1868
1869         switch (level) {
1870         case 3:
1871                 driver = driver_abstract.info_3;
1872                 break;
1873         case 6:
1874                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1875                 driver = &converted_driver;
1876                 break;
1877         default:
1878                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1879                 return WERR_UNKNOWN_LEVEL;
1880         }
1881
1882         short_architecture = get_short_archi(driver->environment);
1883         if (!short_architecture) {
1884                 return WERR_UNKNOWN_PRINTER_DRIVER;
1885         }
1886
1887         fstrcpy(printdollar, "print$");
1888
1889         printdollar_snum = find_service(printdollar);
1890         if (printdollar_snum == -1) {
1891                 *perr = WERR_NO_SUCH_SHARE;
1892                 return WERR_NO_SUCH_SHARE;
1893         }
1894
1895         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1896                                        lp_pathname(printdollar_snum),
1897                                        p->server_info, &oldcwd);
1898         if (!NT_STATUS_IS_OK(nt_status)) {
1899                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1900                          "returned %s\n", nt_errstr(nt_status)));
1901                 *perr = ntstatus_to_werror(nt_status);
1902                 return *perr;
1903         }
1904
1905         new_dir = talloc_asprintf(ctx,
1906                                 "%s/%d",
1907                                 short_architecture,
1908                                 driver->cversion);
1909         if (!new_dir) {
1910                 *perr = WERR_NOMEM;
1911                 goto err_exit;
1912         }
1913         new_dir = driver_unix_convert(conn,new_dir,&st);
1914         if (!new_dir) {
1915                 *perr = WERR_NOMEM;
1916                 goto err_exit;
1917         }
1918
1919         DEBUG(5,("Creating first directory: %s\n", new_dir));
1920
1921         create_directory(conn, NULL, new_dir);
1922
1923         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1924          * listed for this driver which has already been moved, skip it (note:
1925          * drivers may list the same file name several times. Then check if the
1926          * file already exists in archi\cversion\, if so, check that the version
1927          * info (or time stamps if version info is unavailable) is newer (or the
1928          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1929          * Otherwise, delete the file.
1930          *
1931          * If a file is not moved to archi\cversion\ because of an error, all the
1932          * rest of the 'unmoved' driver files are removed from archi\. If one or
1933          * more of the driver's files was already moved to archi\cversion\, it
1934          * potentially leaves the driver in a partially updated state. Version
1935          * trauma will most likely occur if an client attempts to use any printer
1936          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1937          * done is appropriate... later JRR
1938          */
1939
1940         DEBUG(5,("Moving files now !\n"));
1941
1942         if (driver->driverpath && strlen(driver->driverpath)) {
1943
1944                 *perr = move_driver_file_to_download_area(ctx,
1945                                                           conn,
1946                                                           driver->driverpath,
1947                                                           short_architecture,
1948                                                           driver->cversion,
1949                                                           ver);
1950                 if (!W_ERROR_IS_OK(*perr)) {
1951                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1952                                 ver = -1;
1953                         }
1954                         goto err_exit;
1955                 }
1956         }
1957
1958         if (driver->datafile && strlen(driver->datafile)) {
1959                 if (!strequal(driver->datafile, driver->driverpath)) {
1960
1961                         *perr = move_driver_file_to_download_area(ctx,
1962                                                                   conn,
1963                                                                   driver->datafile,
1964                                                                   short_architecture,
1965                                                                   driver->cversion,
1966                                                                   ver);
1967                         if (!W_ERROR_IS_OK(*perr)) {
1968                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1969                                         ver = -1;
1970                                 }
1971                                 goto err_exit;
1972                         }
1973                 }
1974         }
1975
1976         if (driver->configfile && strlen(driver->configfile)) {
1977                 if (!strequal(driver->configfile, driver->driverpath) &&
1978                     !strequal(driver->configfile, driver->datafile)) {
1979
1980                         *perr = move_driver_file_to_download_area(ctx,
1981                                                                   conn,
1982                                                                   driver->configfile,
1983                                                                   short_architecture,
1984                                                                   driver->cversion,
1985                                                                   ver);
1986                         if (!W_ERROR_IS_OK(*perr)) {
1987                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1988                                         ver = -1;
1989                                 }
1990                                 goto err_exit;
1991                         }
1992                 }
1993         }
1994
1995         if (driver->helpfile && strlen(driver->helpfile)) {
1996                 if (!strequal(driver->helpfile, driver->driverpath) &&
1997                     !strequal(driver->helpfile, driver->datafile) &&
1998                     !strequal(driver->helpfile, driver->configfile)) {
1999
2000                         *perr = move_driver_file_to_download_area(ctx,
2001                                                                   conn,
2002                                                                   driver->helpfile,
2003                                                                   short_architecture,
2004                                                                   driver->cversion,
2005                                                                   ver);
2006                         if (!W_ERROR_IS_OK(*perr)) {
2007                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2008                                         ver = -1;
2009                                 }
2010                                 goto err_exit;
2011                         }
2012                 }
2013         }
2014
2015         if (driver->dependentfiles) {
2016                 for (i=0; *driver->dependentfiles[i]; i++) {
2017                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
2018                             !strequal(driver->dependentfiles[i], driver->datafile) &&
2019                             !strequal(driver->dependentfiles[i], driver->configfile) &&
2020                             !strequal(driver->dependentfiles[i], driver->helpfile)) {
2021                                 int j;
2022                                 for (j=0; j < i; j++) {
2023                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
2024                                                 goto NextDriver;
2025                                         }
2026                                 }
2027
2028                                 *perr = move_driver_file_to_download_area(ctx,
2029                                                                           conn,
2030                                                                           driver->dependentfiles[i],
2031                                                                           short_architecture,
2032                                                                           driver->cversion,
2033                                                                           ver);
2034                                 if (!W_ERROR_IS_OK(*perr)) {
2035                                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2036                                                 ver = -1;
2037                                         }
2038                                         goto err_exit;
2039                                 }
2040                         }
2041                 NextDriver: ;
2042                 }
2043         }
2044
2045   err_exit:
2046
2047         if (conn != NULL) {
2048                 vfs_ChDir(conn, oldcwd);
2049                 conn_free_internal(conn);
2050         }
2051
2052         if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2053                 return WERR_OK;
2054         }
2055         if (ver == -1) {
2056                 return WERR_UNKNOWN_PRINTER_DRIVER;
2057         }
2058         return (*perr);
2059 }
2060
2061 /****************************************************************************
2062 ****************************************************************************/
2063
2064 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
2065 {
2066         TALLOC_CTX *ctx = talloc_tos();
2067         int len, buflen;
2068         const char *architecture;
2069         char *directory = NULL;
2070         fstring temp_name;
2071         char *key = NULL;
2072         uint8 *buf;
2073         int i, ret;
2074         TDB_DATA dbuf;
2075
2076         architecture = get_short_archi(driver->environment);
2077         if (!architecture) {
2078                 return (uint32)-1;
2079         }
2080
2081         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2082          * \\server is added in the rpc server layer.
2083          * It does make sense to NOT store the server's name in the printer TDB.
2084          */
2085
2086         directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2087                         architecture, driver->cversion);
2088         if (!directory) {
2089                 return (uint32)-1;
2090         }
2091
2092         /* .inf files do not always list a file for each of the four standard files.
2093          * Don't prepend a path to a null filename, or client claims:
2094          *   "The server on which the printer resides does not have a suitable
2095          *   <printer driver name> printer driver installed. Click OK if you
2096          *   wish to install the driver on your local machine."
2097          */
2098         if (strlen(driver->driverpath)) {
2099                 fstrcpy(temp_name, driver->driverpath);
2100                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
2101         }
2102
2103         if (strlen(driver->datafile)) {
2104                 fstrcpy(temp_name, driver->datafile);
2105                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
2106         }
2107
2108         if (strlen(driver->configfile)) {
2109                 fstrcpy(temp_name, driver->configfile);
2110                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
2111         }
2112
2113         if (strlen(driver->helpfile)) {
2114                 fstrcpy(temp_name, driver->helpfile);
2115                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
2116         }
2117
2118         if (driver->dependentfiles) {
2119                 for (i=0; *driver->dependentfiles[i]; i++) {
2120                         fstrcpy(temp_name, driver->dependentfiles[i]);
2121                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
2122                 }
2123         }
2124
2125         key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2126                         architecture, driver->cversion, driver->name);
2127         if (!key) {
2128                 return (uint32)-1;
2129         }
2130
2131         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2132
2133         buf = NULL;
2134         len = buflen = 0;
2135
2136  again:
2137         len = 0;
2138         len += tdb_pack(buf+len, buflen-len, "dffffffff",
2139                         driver->cversion,
2140                         driver->name,
2141                         driver->environment,
2142                         driver->driverpath,
2143                         driver->datafile,
2144                         driver->configfile,
2145                         driver->helpfile,
2146                         driver->monitorname,
2147                         driver->defaultdatatype);
2148
2149         if (driver->dependentfiles) {
2150                 for (i=0; *driver->dependentfiles[i]; i++) {
2151                         len += tdb_pack(buf+len, buflen-len, "f",
2152                                         driver->dependentfiles[i]);
2153                 }
2154         }
2155
2156         if (len != buflen) {
2157                 buf = (uint8 *)SMB_REALLOC(buf, len);
2158                 if (!buf) {
2159                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2160                         ret = -1;
2161                         goto done;
2162                 }
2163                 buflen = len;
2164                 goto again;
2165         }
2166
2167         dbuf.dptr = buf;
2168         dbuf.dsize = len;
2169
2170         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2171
2172 done:
2173         if (ret)
2174                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2175
2176         SAFE_FREE(buf);
2177         return ret;
2178 }
2179
2180 /****************************************************************************
2181 ****************************************************************************/
2182 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2183 {
2184         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2185
2186         ZERO_STRUCT(info3);
2187         info3.cversion = driver->version;
2188         fstrcpy(info3.name,driver->name);
2189         fstrcpy(info3.environment,driver->environment);
2190         fstrcpy(info3.driverpath,driver->driverpath);
2191         fstrcpy(info3.datafile,driver->datafile);
2192         fstrcpy(info3.configfile,driver->configfile);
2193         fstrcpy(info3.helpfile,driver->helpfile);
2194         fstrcpy(info3.monitorname,driver->monitorname);
2195         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2196         info3.dependentfiles = driver->dependentfiles;
2197
2198         return add_a_printer_driver_3(&info3);
2199 }
2200
2201
2202 /****************************************************************************
2203 ****************************************************************************/
2204 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2205 {
2206         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2207
2208         ZERO_STRUCT(info);
2209
2210         fstrcpy(info.name, driver);
2211         fstrcpy(info.defaultdatatype, "RAW");
2212
2213         fstrcpy(info.driverpath, "");
2214         fstrcpy(info.datafile, "");
2215         fstrcpy(info.configfile, "");
2216         fstrcpy(info.helpfile, "");
2217
2218         if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2219                 return WERR_NOMEM;
2220
2221         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2222         fstrcpy(info.dependentfiles[0], "");
2223
2224         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2225         if (!*info_ptr) {
2226                 SAFE_FREE(info.dependentfiles);
2227                 return WERR_NOMEM;
2228         }
2229
2230         return WERR_OK;
2231 }
2232
2233 /****************************************************************************
2234 ****************************************************************************/
2235 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
2236                                      const char *drivername, const char *arch,
2237                                      uint32_t version)
2238 {
2239         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2240         TDB_DATA dbuf;
2241         const char *architecture;
2242         int len = 0;
2243         int i;
2244         char *key = NULL;
2245
2246         ZERO_STRUCT(driver);
2247
2248         architecture = get_short_archi(arch);
2249         if ( !architecture ) {
2250                 return WERR_UNKNOWN_PRINTER_DRIVER;
2251         }
2252
2253         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2254
2255         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2256                 version = 0;
2257
2258         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2259
2260         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2261                                 architecture, version, drivername) < 0) {
2262                 return WERR_NOMEM;
2263         }
2264
2265         dbuf = tdb_fetch_bystring(tdb_drivers, key);
2266         if (!dbuf.dptr) {
2267                 SAFE_FREE(key);
2268                 return WERR_UNKNOWN_PRINTER_DRIVER;
2269         }
2270
2271         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2272                           &driver.cversion,
2273                           driver.name,
2274                           driver.environment,
2275                           driver.driverpath,
2276                           driver.datafile,
2277                           driver.configfile,
2278                           driver.helpfile,
2279                           driver.monitorname,
2280                           driver.defaultdatatype);
2281
2282         i=0;
2283         while (len < dbuf.dsize) {
2284                 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2285                 if ( !driver.dependentfiles ) {
2286                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2287                         break;
2288                 }
2289
2290                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2291                                   &driver.dependentfiles[i]);
2292                 i++;
2293         }
2294
2295         if ( driver.dependentfiles )
2296                 fstrcpy( driver.dependentfiles[i], "" );
2297
2298         SAFE_FREE(dbuf.dptr);
2299         SAFE_FREE(key);
2300
2301         if (len != dbuf.dsize) {
2302                 SAFE_FREE(driver.dependentfiles);
2303
2304                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2305         }
2306
2307         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2308         if (!*info_ptr) {
2309                 SAFE_FREE(driver.dependentfiles);
2310                 return WERR_NOMEM;
2311         }
2312
2313         return WERR_OK;
2314 }
2315
2316 /****************************************************************************
2317  Debugging function, dump at level 6 the struct in the logs.
2318 ****************************************************************************/
2319
2320 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2321 {
2322         uint32 result;
2323         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2324         int i;
2325
2326         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2327
2328         switch (level)
2329         {
2330                 case 3:
2331                 {
2332                         if (driver.info_3 == NULL)
2333                                 result=5;
2334                         else {
2335                                 info3=driver.info_3;
2336
2337                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
2338                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
2339                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
2340                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
2341                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
2342                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
2343                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
2344                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
2345                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2346
2347                                 for (i=0; info3->dependentfiles &&
2348                                           *info3->dependentfiles[i]; i++) {
2349                                         DEBUGADD(20,("dependentfile:[%s]\n",
2350                                                       info3->dependentfiles[i]));
2351                                 }
2352                                 result=0;
2353                         }
2354                         break;
2355                 }
2356                 default:
2357                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2358                         result=1;
2359                         break;
2360         }
2361
2362         return result;
2363 }
2364
2365 /****************************************************************************
2366 ****************************************************************************/
2367 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2368 {
2369         int len = 0;
2370
2371         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2372
2373         if (!nt_devmode)
2374                 return len;
2375
2376         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2377                         nt_devmode->devicename,
2378                         nt_devmode->formname,
2379
2380                         nt_devmode->specversion,
2381                         nt_devmode->driverversion,
2382                         nt_devmode->size,
2383                         nt_devmode->driverextra,
2384                         nt_devmode->orientation,
2385                         nt_devmode->papersize,
2386                         nt_devmode->paperlength,
2387                         nt_devmode->paperwidth,
2388                         nt_devmode->scale,
2389                         nt_devmode->copies,
2390                         nt_devmode->defaultsource,
2391                         nt_devmode->printquality,
2392                         nt_devmode->color,
2393                         nt_devmode->duplex,
2394                         nt_devmode->yresolution,
2395                         nt_devmode->ttoption,
2396                         nt_devmode->collate,
2397                         nt_devmode->logpixels,
2398
2399                         nt_devmode->fields,
2400                         nt_devmode->bitsperpel,
2401                         nt_devmode->pelswidth,
2402                         nt_devmode->pelsheight,
2403                         nt_devmode->displayflags,
2404                         nt_devmode->displayfrequency,
2405                         nt_devmode->icmmethod,
2406                         nt_devmode->icmintent,
2407                         nt_devmode->mediatype,
2408                         nt_devmode->dithertype,
2409                         nt_devmode->reserved1,
2410                         nt_devmode->reserved2,
2411                         nt_devmode->panningwidth,
2412                         nt_devmode->panningheight,
2413                         nt_devmode->nt_dev_private);
2414
2415         if (nt_devmode->nt_dev_private) {
2416                 len += tdb_pack(buf+len, buflen-len, "B",
2417                                 nt_devmode->driverextra,
2418                                 nt_devmode->nt_dev_private);
2419         }
2420
2421         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2422
2423         return len;
2424 }
2425
2426 /****************************************************************************
2427  Pack all values in all printer keys
2428  ***************************************************************************/
2429
2430 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2431 {
2432         int             len = 0;
2433         int             i, j;
2434         struct regval_blob      *val;
2435         struct regval_ctr       *val_ctr;
2436         char *path = NULL;
2437         int             num_values;
2438
2439         if ( !data )
2440                 return 0;
2441
2442         /* loop over all keys */
2443
2444         for ( i=0; i<data->num_keys; i++ ) {
2445                 val_ctr = data->keys[i].values;
2446                 num_values = regval_ctr_numvals( val_ctr );
2447
2448                 /* pack the keyname followed by a empty value */
2449
2450                 len += tdb_pack(buf+len, buflen-len, "pPdB",
2451                                 &data->keys[i].name,
2452                                 data->keys[i].name,
2453                                 REG_NONE,
2454                                 0,
2455                                 NULL);
2456
2457                 /* now loop over all values */
2458
2459                 for ( j=0; j<num_values; j++ ) {
2460                         /* pathname should be stored as <key>\<value> */
2461
2462                         val = regval_ctr_specific_value( val_ctr, j );
2463                         if (asprintf(&path, "%s\\%s",
2464                                         data->keys[i].name,
2465                                         regval_name(val)) < 0) {
2466                                 return -1;
2467                         }
2468
2469                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2470                                         val,
2471                                         path,
2472                                         regval_type(val),
2473                                         regval_size(val),
2474                                         regval_data_p(val) );
2475
2476                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2477                         SAFE_FREE(path);
2478                 }
2479
2480         }
2481
2482         /* terminator */
2483
2484         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2485
2486         return len;
2487 }
2488
2489
2490 /****************************************************************************
2491  Delete a printer - this just deletes the printer info file, any open
2492  handles are not affected.
2493 ****************************************************************************/
2494
2495 uint32 del_a_printer(const char *sharename)
2496 {
2497         TDB_DATA kbuf;
2498         char *printdb_path = NULL;
2499         TALLOC_CTX *ctx = talloc_tos();
2500
2501         kbuf = make_printer_tdbkey(ctx, sharename);
2502         tdb_delete(tdb_printers, kbuf);
2503
2504         kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2505         tdb_delete(tdb_printers, kbuf);
2506
2507         close_all_print_db();
2508
2509         if (geteuid() == 0) {
2510                 if (asprintf(&printdb_path, "%s%s.tdb",
2511                                 cache_path("printing/"),
2512                                 sharename) < 0) {
2513                         return (uint32)-1;
2514                 }
2515                 unlink(printdb_path);
2516                 SAFE_FREE(printdb_path);
2517         }
2518
2519         return 0;
2520 }
2521
2522 /****************************************************************************
2523 ****************************************************************************/
2524 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2525 {
2526         uint8 *buf;
2527         int buflen, len;
2528         int retlen;
2529         WERROR ret;
2530         TDB_DATA kbuf, dbuf;
2531
2532         /*
2533          * in addprinter: no servername and the printer is the name
2534          * in setprinter: servername is \\server
2535          *                and printer is \\server\\printer
2536          *
2537          * Samba manages only local printers.
2538          * we currently don't support things like i
2539          * path=\\other_server\printer
2540          *
2541          * We only store the printername, not \\server\printername
2542          */
2543
2544         if ( info->servername[0] != '\0' ) {
2545                 trim_string(info->printername, info->servername, NULL);
2546                 trim_char(info->printername, '\\', '\0');
2547                 info->servername[0]='\0';
2548         }
2549
2550         /*
2551          * JFM: one day I'll forget.
2552          * below that's info->portname because that's the SAMBA sharename
2553          * and I made NT 'thinks' it's the portname
2554          * the info->sharename is the thing you can name when you add a printer
2555          * that's the short-name when you create shared printer for 95/98
2556          * So I've made a limitation in SAMBA: you can only have 1 printer model
2557          * behind a SAMBA share.
2558          */
2559
2560         buf = NULL;
2561         buflen = 0;
2562
2563  again:
2564         len = 0;
2565         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2566                         info->attributes,
2567                         info->priority,
2568                         info->default_priority,
2569                         info->starttime,
2570                         info->untiltime,
2571                         info->status,
2572                         info->cjobs,
2573                         info->averageppm,
2574                         info->changeid,
2575                         info->c_setprinter,
2576                         info->setuptime,
2577                         info->servername,
2578                         info->printername,
2579                         info->sharename,
2580                         info->portname,
2581                         info->drivername,
2582                         info->comment,
2583                         info->location,
2584                         info->sepfile,
2585                         info->printprocessor,
2586                         info->datatype,
2587                         info->parameters);
2588
2589         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2590         retlen = pack_values( info->data, buf+len, buflen-len );
2591         if (retlen == -1) {
2592                 ret = WERR_NOMEM;
2593                 goto done;
2594         }
2595         len += retlen;
2596
2597         if (buflen != len) {
2598                 buf = (uint8 *)SMB_REALLOC(buf, len);
2599                 if (!buf) {
2600                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2601                         ret = WERR_NOMEM;
2602                         goto done;
2603                 }
2604                 buflen = len;
2605                 goto again;
2606         }
2607
2608         kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2609
2610         dbuf.dptr = buf;
2611         dbuf.dsize = len;
2612
2613         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2614
2615 done:
2616         if (!W_ERROR_IS_OK(ret))
2617                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2618
2619         SAFE_FREE(buf);
2620
2621         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2622                  info->sharename, info->drivername, info->portname, len));
2623
2624         return ret;
2625 }
2626
2627
2628 /****************************************************************************
2629  Malloc and return an NT devicemode.
2630 ****************************************************************************/
2631
2632 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2633 {
2634
2635         char adevice[MAXDEVICENAME];
2636         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2637
2638         if (nt_devmode == NULL) {
2639                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2640                 return NULL;
2641         }
2642
2643         ZERO_STRUCTP(nt_devmode);
2644
2645         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2646         fstrcpy(nt_devmode->devicename, adevice);
2647
2648         fstrcpy(nt_devmode->formname, "Letter");
2649
2650         nt_devmode->specversion      = 0x0401;
2651         nt_devmode->driverversion    = 0x0400;
2652         nt_devmode->size             = 0x00DC;
2653         nt_devmode->driverextra      = 0x0000;
2654         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2655                                        DEFAULTSOURCE | COPIES | SCALE |
2656                                        PAPERSIZE | ORIENTATION;
2657         nt_devmode->orientation      = 1;
2658         nt_devmode->papersize        = PAPER_LETTER;
2659         nt_devmode->paperlength      = 0;
2660         nt_devmode->paperwidth       = 0;
2661         nt_devmode->scale            = 0x64;
2662         nt_devmode->copies           = 1;
2663         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2664         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2665         nt_devmode->color            = COLOR_MONOCHROME;
2666         nt_devmode->duplex           = DUP_SIMPLEX;
2667         nt_devmode->yresolution      = 0;
2668         nt_devmode->ttoption         = TT_SUBDEV;
2669         nt_devmode->collate          = COLLATE_FALSE;
2670         nt_devmode->icmmethod        = 0;
2671         nt_devmode->icmintent        = 0;
2672         nt_devmode->mediatype        = 0;
2673         nt_devmode->dithertype       = 0;
2674
2675         /* non utilisés par un driver d'imprimante */
2676         nt_devmode->logpixels        = 0;
2677         nt_devmode->bitsperpel       = 0;
2678         nt_devmode->pelswidth        = 0;
2679         nt_devmode->pelsheight       = 0;
2680         nt_devmode->displayflags     = 0;
2681         nt_devmode->displayfrequency = 0;
2682         nt_devmode->reserved1        = 0;
2683         nt_devmode->reserved2        = 0;
2684         nt_devmode->panningwidth     = 0;
2685         nt_devmode->panningheight    = 0;
2686
2687         nt_devmode->nt_dev_private = NULL;
2688         return nt_devmode;
2689 }
2690
2691 /****************************************************************************
2692  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2693 ****************************************************************************/
2694
2695 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2696 {
2697         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2698
2699         if(nt_devmode == NULL)
2700                 return;
2701
2702         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2703
2704         SAFE_FREE(nt_devmode->nt_dev_private);
2705         SAFE_FREE(*devmode_ptr);
2706 }
2707
2708 /****************************************************************************
2709  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2710 ****************************************************************************/
2711
2712 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2713 {
2714         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2715
2716         if ( !info )
2717                 return;
2718
2719         free_nt_devicemode(&info->devmode);
2720
2721         TALLOC_FREE( *info_ptr );
2722 }
2723
2724
2725 /****************************************************************************
2726 ****************************************************************************/
2727 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2728 {
2729         int len = 0;
2730         int extra_len = 0;
2731         NT_DEVICEMODE devmode;
2732
2733         ZERO_STRUCT(devmode);
2734
2735         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2736
2737         if (!*nt_devmode) return len;
2738
2739         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2740                           devmode.devicename,
2741                           devmode.formname,
2742
2743                           &devmode.specversion,
2744                           &devmode.driverversion,
2745                           &devmode.size,
2746                           &devmode.driverextra,
2747                           &devmode.orientation,
2748                           &devmode.papersize,
2749                           &devmode.paperlength,
2750                           &devmode.paperwidth,
2751                           &devmode.scale,
2752                           &devmode.copies,
2753                           &devmode.defaultsource,
2754                           &devmode.printquality,
2755                           &devmode.color,
2756                           &devmode.duplex,
2757                           &devmode.yresolution,
2758                           &devmode.ttoption,
2759                           &devmode.collate,
2760                           &devmode.logpixels,
2761
2762                           &devmode.fields,
2763                           &devmode.bitsperpel,
2764                           &devmode.pelswidth,
2765                           &devmode.pelsheight,
2766                           &devmode.displayflags,
2767                           &devmode.displayfrequency,
2768                           &devmode.icmmethod,
2769                           &devmode.icmintent,
2770                           &devmode.mediatype,
2771                           &devmode.dithertype,
2772                           &devmode.reserved1,
2773                           &devmode.reserved2,
2774                           &devmode.panningwidth,
2775                           &devmode.panningheight,
2776                           &devmode.nt_dev_private);
2777
2778         if (devmode.nt_dev_private) {
2779                 /* the len in tdb_unpack is an int value and
2780                  * devmode.driverextra is only a short
2781                  */
2782                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2783                 devmode.driverextra=(uint16)extra_len;
2784
2785                 /* check to catch an invalid TDB entry so we don't segfault */
2786                 if (devmode.driverextra == 0) {
2787                         devmode.nt_dev_private = NULL;
2788                 }
2789         }
2790
2791         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2792         if (!*nt_devmode) {
2793                 SAFE_FREE(devmode.nt_dev_private);
2794                 return -1;
2795         }
2796
2797         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2798         if (devmode.nt_dev_private)
2799                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2800
2801         return len;
2802 }
2803
2804 /****************************************************************************
2805  Allocate and initialize a new slot.
2806 ***************************************************************************/
2807
2808 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2809 {
2810         NT_PRINTER_KEY  *d;
2811         int             key_index;
2812
2813         if ( !name || !data )
2814                 return -1;
2815
2816         /* allocate another slot in the NT_PRINTER_KEY array */
2817
2818         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2819                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2820                 return -1;
2821         }
2822
2823         data->keys = d;
2824
2825         key_index = data->num_keys;
2826
2827         /* initialze new key */
2828
2829         data->keys[key_index].name = talloc_strdup( data, name );
2830
2831         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
2832                 return -1;
2833
2834         data->num_keys++;
2835
2836         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2837
2838         return key_index;
2839 }
2840
2841 /****************************************************************************
2842  search for a registry key name in the existing printer data
2843  ***************************************************************************/
2844
2845 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2846 {
2847         int i;
2848
2849         for ( i=0; i<data->num_keys; i++ ) {
2850                 if ( strequal( data->keys[i].name, name ) ) {
2851
2852                         /* cleanup memory */
2853
2854                         TALLOC_FREE( data->keys[i].name );
2855                         TALLOC_FREE( data->keys[i].values );
2856
2857                         /* if not the end of the array, move remaining elements down one slot */
2858
2859                         data->num_keys--;
2860                         if ( data->num_keys && (i < data->num_keys) )
2861                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2862
2863                         break;
2864                 }
2865         }
2866
2867
2868         return data->num_keys;
2869 }
2870
2871 /****************************************************************************
2872  search for a registry key name in the existing printer data
2873  ***************************************************************************/
2874
2875 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2876 {
2877         int             key_index = -1;
2878         int             i;
2879
2880         if ( !data || !name )
2881                 return -1;
2882
2883         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2884
2885         /* loop over all existing keys */
2886
2887         for ( i=0; i<data->num_keys; i++ ) {
2888                 if ( strequal(data->keys[i].name, name) ) {
2889                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2890                         key_index = i;
2891                         break;
2892
2893                 }
2894         }
2895
2896         return key_index;
2897 }
2898
2899 /****************************************************************************
2900  ***************************************************************************/
2901
2902 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2903 {
2904         int     i, j;
2905         int     key_len;
2906         int     num_subkeys = 0;
2907         char    *p;
2908         fstring *subkeys_ptr = NULL;
2909         fstring subkeyname;
2910
2911         *subkeys = NULL;
2912
2913         if ( !data )
2914                 return 0;
2915
2916         if ( !key )
2917                 return -1;
2918
2919         /* special case of asking for the top level printer data registry key names */
2920
2921         if ( strlen(key) == 0 ) {
2922                 for ( i=0; i<data->num_keys; i++ ) {
2923
2924                         /* found a match, so allocate space and copy the name */
2925
2926                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2927                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2928                                         num_subkeys+1));
2929                                 return -1;
2930                         }
2931
2932                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2933                         num_subkeys++;
2934                 }
2935
2936                 goto done;
2937         }
2938
2939         /* asking for the subkeys of some key */
2940         /* subkey paths are stored in the key name using '\' as the delimiter */
2941
2942         for ( i=0; i<data->num_keys; i++ ) {
2943                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2944
2945                         /* if we found the exact key, then break */
2946                         key_len = strlen( key );
2947                         if ( strlen(data->keys[i].name) == key_len )
2948                                 break;
2949
2950                         /* get subkey path */
2951
2952                         p = data->keys[i].name + key_len;
2953                         if ( *p == '\\' )
2954                                 p++;
2955                         fstrcpy( subkeyname, p );
2956                         if ( (p = strchr( subkeyname, '\\' )) )
2957                                 *p = '\0';
2958
2959                         /* don't add a key more than once */
2960
2961                         for ( j=0; j<num_subkeys; j++ ) {
2962                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2963                                         break;
2964                         }
2965
2966                         if ( j != num_subkeys )
2967                                 continue;
2968
2969                         /* found a match, so allocate space and copy the name */
2970
2971                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2972                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2973                                         num_subkeys+1));
2974                                 return 0;
2975                         }
2976
2977                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2978                         num_subkeys++;
2979                 }
2980
2981         }
2982
2983         /* return error if the key was not found */
2984
2985         if ( i == data->num_keys ) {
2986                 SAFE_FREE(subkeys_ptr);
2987                 return -1;
2988         }
2989
2990 done:
2991         /* tag off the end */
2992
2993         if (num_subkeys)
2994                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2995
2996         *subkeys = subkeys_ptr;
2997
2998         return num_subkeys;
2999 }
3000
3001 #ifdef HAVE_ADS
3002 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3003                             const char *sz)
3004 {
3005         smb_ucs2_t conv_str[1024];
3006         size_t str_size;
3007
3008         regval_ctr_delvalue(ctr, val_name);
3009         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
3010                              STR_TERMINATE | STR_NOALIGN);
3011         regval_ctr_addvalue(ctr, val_name, REG_SZ,
3012                             (char *) conv_str, str_size);
3013 }
3014
3015 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3016                                uint32 dword)
3017 {
3018         regval_ctr_delvalue(ctr, val_name);
3019         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3020                             (char *) &dword, sizeof(dword));
3021 }
3022
3023 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3024                               bool b)
3025 {
3026         uint8 bin_bool = (b ? 1 : 0);
3027         regval_ctr_delvalue(ctr, val_name);
3028         regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3029                             (char *) &bin_bool, sizeof(bin_bool));
3030 }
3031
3032 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3033                                          const char *multi_sz)
3034 {
3035         smb_ucs2_t *conv_strs = NULL;
3036         size_t str_size;
3037
3038         /* a multi-sz has to have a null string terminator, i.e., the last
3039            string must be followed by two nulls */
3040         str_size = strlen(multi_sz) + 2;
3041         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
3042         if (!conv_strs) {
3043                 return;
3044         }
3045
3046         /* Change to byte units. */
3047         str_size *= sizeof(smb_ucs2_t);
3048         push_ucs2(NULL, conv_strs, multi_sz, str_size,
3049                   STR_TERMINATE | STR_NOALIGN);
3050
3051         regval_ctr_delvalue(ctr, val_name);
3052         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
3053                             (char *) conv_strs, str_size);
3054         SAFE_FREE(conv_strs);
3055 }
3056
3057 /****************************************************************************
3058  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3059  *
3060  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3061  * @return bool indicating success or failure
3062  ***************************************************************************/
3063
3064 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3065 {
3066         struct regval_ctr *ctr = NULL;
3067         fstring longname;
3068         const char *dnssuffix;
3069         char *allocated_string = NULL;
3070         const char *ascii_str;
3071         int i;
3072
3073         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3074                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3075         ctr = info2->data->keys[i].values;
3076
3077         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3078         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3079
3080         /* we make the assumption that the netbios name is the same
3081            as the DNS name sinc ethe former will be what we used to
3082            join the domain */
3083
3084         dnssuffix = get_mydnsdomname(talloc_tos());
3085         if (dnssuffix && *dnssuffix) {
3086                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3087         } else {
3088                 fstrcpy( longname, global_myname() );
3089         }
3090
3091         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3092
3093         if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3094                 return false;
3095         }
3096         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3097         SAFE_FREE(allocated_string);
3098
3099         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3100         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3101         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3102         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3103         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3104         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3105         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3106         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3107         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3108
3109         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3110                           (info2->attributes &
3111                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3112
3113         switch (info2->attributes & 0x3) {
3114         case 0:
3115                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3116                 break;
3117         case 1:
3118                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3119                 break;
3120         case 2:
3121                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3122                 break;
3123         default:
3124                 ascii_str = "unknown";
3125         }
3126         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3127
3128         return True;
3129 }
3130
3131 /*****************************************************************
3132  ****************************************************************/
3133
3134 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3135                                struct GUID guid)
3136 {
3137         int i;
3138         struct regval_ctr *ctr=NULL;
3139         UNISTR2 unistr_guid;
3140
3141         /* find the DsSpooler key */
3142         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3143                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3144         ctr = info2->data->keys[i].values;
3145
3146         regval_ctr_delvalue(ctr, "objectGUID");
3147
3148         /* We used to store this as a REG_BINARY but that causes
3149            Vista to whine */
3150
3151         ZERO_STRUCT( unistr_guid );
3152
3153         init_unistr2( &unistr_guid, GUID_string(talloc_tos(), &guid),
3154                       UNI_STR_TERMINATE );
3155
3156         regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3157                             (char *)unistr_guid.buffer,
3158                             unistr_guid.uni_max_len*2);
3159
3160 }
3161
3162 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3163                                      NT_PRINTER_INFO_LEVEL *printer)
3164 {
3165         ADS_STATUS ads_rc;
3166         LDAPMessage *res;
3167         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3168         char *srv_dn_utf8, **srv_cn_utf8;
3169         TALLOC_CTX *ctx;
3170         ADS_MODLIST mods;
3171         const char *attrs[] = {"objectGUID", NULL};
3172         struct GUID guid;
3173         WERROR win_rc = WERR_OK;
3174         size_t converted_size;
3175
3176         /* build the ads mods */
3177         ctx = talloc_init("nt_printer_publish_ads");
3178         if (ctx == NULL) {
3179                 return WERR_NOMEM;
3180         }
3181
3182         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3183
3184         /* figure out where to publish */
3185         ads_find_machine_acct(ads, &res, global_myname());
3186
3187         /* We use ldap_get_dn here as we need the answer
3188          * in utf8 to call ldap_explode_dn(). JRA. */
3189
3190         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3191         if (!srv_dn_utf8) {
3192                 TALLOC_FREE(ctx);
3193                 return WERR_SERVER_UNAVAILABLE;
3194         }
3195         ads_msgfree(ads, res);
3196         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3197         if (!srv_cn_utf8) {
3198                 TALLOC_FREE(ctx);
3199                 ldap_memfree(srv_dn_utf8);
3200                 return WERR_SERVER_UNAVAILABLE;
3201         }
3202         /* Now convert to CH_UNIX. */
3203         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3204                 TALLOC_FREE(ctx);
3205                 ldap_memfree(srv_dn_utf8);
3206                 ldap_memfree(srv_cn_utf8);
3207                 return WERR_SERVER_UNAVAILABLE;
3208         }
3209         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3210                 TALLOC_FREE(ctx);
3211                 ldap_memfree(srv_dn_utf8);
3212                 ldap_memfree(srv_cn_utf8);
3213                 TALLOC_FREE(srv_dn);
3214                 return WERR_SERVER_UNAVAILABLE;
3215         }
3216
3217         ldap_memfree(srv_dn_utf8);
3218         ldap_memfree(srv_cn_utf8);
3219
3220         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3221         if (!srv_cn_escaped) {
3222                 TALLOC_FREE(ctx);
3223                 return WERR_SERVER_UNAVAILABLE;
3224         }
3225         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3226         if (!sharename_escaped) {
3227                 SAFE_FREE(srv_cn_escaped);
3228                 TALLOC_FREE(ctx);
3229                 return WERR_SERVER_UNAVAILABLE;
3230         }
3231
3232         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3233
3234         SAFE_FREE(srv_cn_escaped);
3235         SAFE_FREE(sharename_escaped);
3236
3237         mods = ads_init_mods(ctx);
3238
3239         if (mods == NULL) {
3240                 SAFE_FREE(prt_dn);
3241                 TALLOC_FREE(ctx);
3242                 return WERR_NOMEM;
3243         }
3244
3245         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3246         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3247                     printer->info_2->sharename);
3248
3249         /* publish it */
3250         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3251         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3252                 int i;
3253                 for (i=0; mods[i] != 0; i++)
3254                         ;
3255                 mods[i] = (LDAPMod *)-1;
3256                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3257         }
3258
3259         if (!ADS_ERR_OK(ads_rc))
3260                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3261
3262         /* retreive the guid and store it locally */
3263         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3264                 ZERO_STRUCT(guid);
3265                 ads_pull_guid(ads, res, &guid);
3266                 ads_msgfree(ads, res);
3267                 store_printer_guid(printer->info_2, guid);
3268                 win_rc = mod_a_printer(printer, 2);
3269         }
3270         TALLOC_FREE(ctx);
3271
3272         return win_rc;
3273 }
3274
3275 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3276                                        NT_PRINTER_INFO_LEVEL *printer)
3277 {
3278         ADS_STATUS ads_rc;
3279         LDAPMessage *res = NULL;
3280         char *prt_dn = NULL;
3281
3282         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3283
3284         /* remove the printer from the directory */
3285         ads_rc = ads_find_printer_on_server(ads, &res,
3286                             printer->info_2->sharename, global_myname());
3287
3288         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3289                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3290                 if (!prt_dn) {
3291                         ads_msgfree(ads, res);
3292                         return WERR_NOMEM;
3293                 }
3294                 ads_rc = ads_del_dn(ads, prt_dn);
3295                 TALLOC_FREE(prt_dn);
3296         }
3297
3298         if (res) {
3299                 ads_msgfree(ads, res);
3300         }
3301         return WERR_OK;
3302 }
3303
3304 /****************************************************************************
3305  * Publish a printer in the directory
3306  *
3307  * @param snum describing printer service
3308  * @return WERROR indicating status of publishing
3309  ***************************************************************************/
3310
3311 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3312 {
3313         ADS_STATUS ads_rc;
3314         ADS_STRUCT *ads = NULL;
3315         NT_PRINTER_INFO_LEVEL *printer = NULL;
3316         WERROR win_rc;
3317
3318         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3319         if (!W_ERROR_IS_OK(win_rc))
3320                 goto done;
3321
3322         switch (action) {
3323         case DSPRINT_PUBLISH:
3324         case DSPRINT_UPDATE:
3325                 /* set the DsSpooler info and attributes */
3326                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3327                         win_rc = WERR_NOMEM;
3328                         goto done;
3329                 }
3330
3331                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3332                 break;
3333         case DSPRINT_UNPUBLISH:
3334                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3335                 break;
3336         default:
3337                 win_rc = WERR_NOT_SUPPORTED;
3338                 goto done;
3339         }
3340
3341         win_rc = mod_a_printer(printer, 2);
3342         if (!W_ERROR_IS_OK(win_rc)) {
3343                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3344                 goto done;
3345         }
3346
3347         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3348         if (!ads) {
3349                 DEBUG(3, ("ads_init() failed\n"));
3350                 win_rc = WERR_SERVER_UNAVAILABLE;
3351                 goto done;
3352         }
3353         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3354         SAFE_FREE(ads->auth.password);
3355         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3356                 NULL, NULL);
3357
3358         /* ads_connect() will find the DC for us */
3359         ads_rc = ads_connect(ads);
3360         if (!ADS_ERR_OK(ads_rc)) {
3361                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3362                 win_rc = WERR_ACCESS_DENIED;
3363                 goto done;
3364         }
3365
3366         switch (action) {
3367         case DSPRINT_PUBLISH:
3368         case DSPRINT_UPDATE:
3369                 win_rc = nt_printer_publish_ads(ads, printer);
3370                 break;
3371         case DSPRINT_UNPUBLISH:
3372                 win_rc = nt_printer_unpublish_ads(ads, printer);
3373                 break;
3374         }
3375
3376 done:
3377         free_a_printer(&printer, 2);
3378         ads_destroy(&ads);
3379         return win_rc;
3380 }
3381
3382 WERROR check_published_printers(void)
3383 {
3384         ADS_STATUS ads_rc;
3385         ADS_STRUCT *ads = NULL;
3386         int snum;
3387         int n_services = lp_numservices();
3388         NT_PRINTER_INFO_LEVEL *printer = NULL;
3389
3390         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3391         if (!ads) {
3392                 DEBUG(3, ("ads_init() failed\n"));
3393                 return WERR_SERVER_UNAVAILABLE;
3394         }
3395         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3396         SAFE_FREE(ads->auth.password);
3397         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3398                 NULL, NULL);
3399
3400         /* ads_connect() will find the DC for us */
3401         ads_rc = ads_connect(ads);
3402         if (!ADS_ERR_OK(ads_rc)) {
3403                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3404                 ads_destroy(&ads);
3405                 ads_kdestroy("MEMORY:prtpub_cache");
3406                 return WERR_ACCESS_DENIED;
3407         }
3408
3409         for (snum = 0; snum < n_services; snum++) {
3410                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3411                         continue;
3412
3413                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3414                                                 lp_servicename(snum))) &&
3415                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3416                         nt_printer_publish_ads(ads, printer);
3417
3418                 free_a_printer(&printer, 2);
3419         }
3420
3421         ads_destroy(&ads);
3422         ads_kdestroy("MEMORY:prtpub_cache");
3423         return WERR_OK;
3424 }
3425
3426 bool is_printer_published(Printer_entry *print_hnd, int snum,
3427                           struct GUID *guid)
3428 {
3429         NT_PRINTER_INFO_LEVEL *printer = NULL;
3430         struct regval_ctr *ctr;
3431         struct regval_blob *guid_val;
3432         WERROR win_rc;
3433         int i;
3434         bool ret = False;
3435
3436         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3437
3438         if (!W_ERROR_IS_OK(win_rc) ||
3439             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3440             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3441             !(ctr = printer->info_2->data->keys[i].values) ||
3442             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3443         {
3444                 free_a_printer(&printer, 2);
3445                 return False;
3446         }
3447
3448         /* fetching printer guids really ought to be a separate function. */
3449
3450         if ( guid ) {
3451                 fstring guid_str;
3452
3453                 /* We used to store the guid as REG_BINARY, then swapped
3454                    to REG_SZ for Vista compatibility so check for both */
3455
3456                 switch ( regval_type(guid_val) ){
3457                 case REG_SZ:
3458                         rpcstr_pull( guid_str, regval_data_p(guid_val),
3459                                      sizeof(guid_str)-1, -1, STR_TERMINATE );
3460                         ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3461                         break;
3462                 case REG_BINARY:
3463                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3464                                 ret = False;
3465                                 break;
3466                         }
3467                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3468                         break;
3469                 default:
3470                         DEBUG(0,("is_printer_published: GUID value stored as "
3471                                  "invaluid type (%d)\n", regval_type(guid_val) ));
3472                         break;
3473                 }
3474         }
3475
3476         free_a_printer(&printer, 2);
3477         return ret;
3478 }
3479 #else
3480 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3481 {
3482         return WERR_OK;
3483 }
3484
3485 WERROR check_published_printers(void)
3486 {
3487         return WERR_OK;
3488 }
3489
3490 bool is_printer_published(Printer_entry *print_hnd, int snum,
3491                           struct GUID *guid)
3492 {
3493         return False;
3494 }
3495 #endif /* HAVE_ADS */
3496
3497 /****************************************************************************
3498  ***************************************************************************/
3499
3500 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3501 {
3502         NT_PRINTER_DATA *data;
3503         int             i;
3504         int             removed_keys = 0;
3505         int             empty_slot;
3506
3507         data = p2->data;
3508         empty_slot = data->num_keys;
3509
3510         if ( !key )
3511                 return WERR_INVALID_PARAM;
3512
3513         /* remove all keys */
3514
3515         if ( !strlen(key) ) {
3516
3517                 TALLOC_FREE( data );
3518
3519                 p2->data = NULL;
3520
3521                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3522                         p2->printername ));
3523
3524                 return WERR_OK;
3525         }
3526
3527         /* remove a specific key (and all subkeys) */
3528
3529         for ( i=0; i<data->num_keys; i++ ) {
3530                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3531                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3532                                 data->keys[i].name));
3533
3534                         TALLOC_FREE( data->keys[i].name );
3535                         TALLOC_FREE( data->keys[i].values );
3536
3537                         /* mark the slot as empty */
3538
3539                         ZERO_STRUCTP( &data->keys[i] );
3540                 }
3541         }
3542
3543         /* find the first empty slot */
3544
3545         for ( i=0; i<data->num_keys; i++ ) {
3546                 if ( !data->keys[i].name ) {
3547                         empty_slot = i;
3548                         removed_keys++;
3549                         break;
3550                 }
3551         }
3552
3553         if ( i == data->num_keys )
3554                 /* nothing was removed */
3555                 return WERR_INVALID_PARAM;
3556
3557         /* move everything down */
3558
3559         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3560                 if ( data->keys[i].name ) {
3561                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3562                         ZERO_STRUCTP( &data->keys[i] );
3563                         empty_slot++;
3564                         removed_keys++;
3565                 }
3566         }
3567
3568         /* update count */
3569
3570         data->num_keys -= removed_keys;
3571
3572         /* sanity check to see if anything is left */
3573
3574         if ( !data->num_keys ) {
3575                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3576
3577                 SAFE_FREE( data->keys );
3578                 ZERO_STRUCTP( data );
3579         }
3580
3581         return WERR_OK;
3582 }
3583
3584 /****************************************************************************
3585  ***************************************************************************/
3586
3587 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3588 {
3589         WERROR          result = WERR_OK;
3590         int             key_index;
3591
3592         /* we must have names on non-zero length */
3593
3594         if ( !key || !*key|| !value || !*value )
3595                 return WERR_INVALID_NAME;
3596
3597         /* find the printer key first */
3598
3599         key_index = lookup_printerkey( p2->data, key );
3600         if ( key_index == -1 )
3601                 return WERR_OK;
3602
3603         /* make sure the value exists so we can return the correct error code */
3604
3605         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3606                 return WERR_BADFILE;
3607
3608         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3609
3610         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3611                 key, value ));
3612
3613         return result;
3614 }
3615
3616 /****************************************************************************
3617  ***************************************************************************/
3618
3619 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3620                            uint32 type, uint8 *data, int real_len )
3621 {
3622         WERROR          result = WERR_OK;
3623         int             key_index;
3624
3625         /* we must have names on non-zero length */
3626
3627         if ( !key || !*key|| !value || !*value )
3628                 return WERR_INVALID_NAME;
3629
3630         /* find the printer key first */
3631
3632         key_index = lookup_printerkey( p2->data, key );
3633         if ( key_index == -1 )
3634                 key_index = add_new_printer_key( p2->data, key );
3635
3636         if ( key_index == -1 )
3637                 return WERR_NOMEM;
3638
3639         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3640                 type, (const char *)data, real_len );
3641
3642         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3643                 key, value, type, real_len  ));
3644
3645         return result;
3646 }
3647
3648 /****************************************************************************
3649  ***************************************************************************/
3650
3651 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3652 {
3653         int             key_index;
3654
3655         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3656                 return NULL;
3657
3658         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3659                 key, value ));
3660
3661         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3662 }
3663
3664 /****************************************************************************
3665  Unpack a list of registry values frem the TDB
3666  ***************************************************************************/
3667
3668 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3669 {
3670         int             len = 0;
3671         uint32          type;
3672         fstring string;
3673         const char *valuename = NULL;
3674         const char *keyname = NULL;
3675         char            *str;
3676         int             size;
3677         uint8           *data_p;
3678         struct regval_blob      *regval_p;
3679         int             key_index;
3680
3681         /* add the "PrinterDriverData" key first for performance reasons */
3682
3683         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3684
3685         /* loop and unpack the rest of the registry values */
3686
3687         while ( True ) {
3688
3689                 /* check to see if there are any more registry values */
3690
3691                 regval_p = NULL;
3692                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3693                 if ( !regval_p )
3694                         break;
3695
3696                 /* unpack the next regval */
3697
3698                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3699                                   string,
3700                                   &type,
3701                                   &size,
3702                                   &data_p);
3703
3704                 /* lookup for subkey names which have a type of REG_NONE */
3705                 /* there's no data with this entry */
3706
3707                 if ( type == REG_NONE ) {
3708                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3709                                 add_new_printer_key( printer_data, string );
3710                         continue;
3711                 }
3712
3713                 /*
3714                  * break of the keyname from the value name.
3715                  * Valuenames can have embedded '\'s so be careful.
3716                  * only support one level of keys.  See the
3717                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3718                  * -- jerry
3719                  */
3720
3721                 str = strchr_m( string, '\\');
3722
3723                 /* Put in "PrinterDriverData" is no key specified */
3724
3725                 if ( !str ) {
3726                         keyname = SPOOL_PRINTERDATA_KEY;
3727                         valuename = string;
3728                 }
3729                 else {
3730                         *str = '\0';
3731                         keyname = string;
3732                         valuename = str+1;
3733                 }
3734
3735                 /* see if we need a new key */
3736
3737                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3738                         key_index = add_new_printer_key( printer_data, keyname );
3739
3740                 if ( key_index == -1 ) {
3741                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3742                                 keyname));
3743                         break;
3744                 }
3745
3746                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3747
3748                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3749                    Thanks to Martin Zielinski for the hint. */
3750
3751                 if ( type == REG_BINARY &&
3752                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3753                      strequal( valuename, "objectGUID" ) )
3754                 {
3755                         struct GUID guid;
3756                         UNISTR2 unistr_guid;
3757
3758                         ZERO_STRUCT( unistr_guid );
3759
3760                         /* convert the GUID to a UNICODE string */
3761
3762                         memcpy( &guid, data_p, sizeof(struct GUID) );
3763
3764                         init_unistr2( &unistr_guid,
3765                                       GUID_string(talloc_tos(), &guid),
3766                                       UNI_STR_TERMINATE );
3767
3768                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3769                                              valuename, REG_SZ,
3770                                              (const char *)unistr_guid.buffer,
3771                                              unistr_guid.uni_str_len*2 );
3772
3773                 } else {
3774                         /* add the value */
3775
3776                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3777                                              valuename, type, (const char *)data_p,
3778                                              size );
3779                 }
3780
3781                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3782
3783         }
3784
3785         return len;
3786 }
3787
3788 /****************************************************************************
3789  ***************************************************************************/
3790
3791 static char *last_from;
3792 static char *last_to;
3793
3794 static const char *get_last_from(void)
3795 {
3796         if (!last_from) {
3797                 return "";
3798         }
3799         return last_from;
3800 }
3801
3802 static const char *get_last_to(void)
3803 {
3804         if (!last_to) {
3805                 return "";
3806         }
3807         return last_to;
3808 }
3809
3810 static bool set_last_from_to(const char *from, const char *to)
3811 {
3812         char *orig_from = last_from;
3813         char *orig_to = last_to;
3814
3815         last_from = SMB_STRDUP(from);
3816         last_to = SMB_STRDUP(to);
3817
3818         SAFE_FREE(orig_from);
3819         SAFE_FREE(orig_to);
3820
3821         if (!last_from || !last_to) {
3822                 SAFE_FREE(last_from);
3823                 SAFE_FREE(last_to);
3824                 return false;
3825         }
3826         return true;
3827 }
3828
3829 static void map_to_os2_driver(fstring drivername)
3830 {
3831         char *mapfile = lp_os2_driver_map();
3832         char **lines = NULL;
3833         int numlines = 0;
3834         int i;
3835
3836         if (!strlen(drivername))
3837                 return;
3838
3839         if (!*mapfile)
3840                 return;
3841
3842         if (strequal(drivername,get_last_from())) {
3843                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3844                         drivername,get_last_to()));
3845                 fstrcpy(drivername,get_last_to());
3846                 return;
3847         }
3848
3849         lines = file_lines_load(mapfile, &numlines,0,NULL);
3850         if (numlines == 0 || lines == NULL) {
3851                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3852                 TALLOC_FREE(lines);
3853                 return;
3854         }
3855
3856         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3857
3858         for( i = 0; i < numlines; i++) {
3859                 char *nt_name = lines[i];
3860                 char *os2_name = strchr(nt_name,'=');
3861
3862                 if (!os2_name)
3863                         continue;
3864
3865                 *os2_name++ = 0;
3866
3867                 while (isspace(*nt_name))
3868                         nt_name++;
3869
3870                 if (!*nt_name || strchr("#;",*nt_name))
3871                         continue;
3872
3873                 {
3874                         int l = strlen(nt_name);
3875                         while (l && isspace(nt_name[l-1])) {
3876                                 nt_name[l-1] = 0;
3877                                 l--;
3878                         }
3879                 }
3880
3881                 while (isspace(*os2_name))
3882                         os2_name++;
3883
3884                 {
3885                         int l = strlen(os2_name);
3886                         while (l && isspace(os2_name[l-1])) {
3887                                 os2_name[l-1] = 0;
3888                                 l--;
3889                         }
3890                 }
3891
3892                 if (strequal(nt_name,drivername)) {
3893                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3894                         set_last_from_to(drivername,os2_name);
3895                         fstrcpy(drivername,os2_name);
3896                         TALLOC_FREE(lines);
3897                         return;
3898                 }
3899         }
3900
3901         TALLOC_FREE(lines);
3902 }
3903
3904 /****************************************************************************
3905  Get a default printer info 2 struct.
3906 ****************************************************************************/
3907
3908 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3909                                 const char *servername,
3910                                 const char* sharename,
3911                                 bool get_loc_com)
3912 {
3913         int snum = lp_servicenumber(sharename);
3914
3915         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3916         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3917                 servername, sharename);
3918         fstrcpy(info->sharename, sharename);
3919         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3920
3921         /* by setting the driver name to an empty string, a local NT admin
3922            can now run the **local** APW to install a local printer driver
3923            for a Samba shared printer in 2.2.  Without this, drivers **must** be
3924            installed on the Samba server for NT clients --jerry */
3925 #if 0   /* JERRY --do not uncomment-- */
3926         if (!*info->drivername)
3927                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3928 #endif
3929
3930
3931         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3932
3933         strlcpy(info->comment, "", sizeof(info->comment));
3934         fstrcpy(info->printprocessor, "winprint");
3935         fstrcpy(info->datatype, "RAW");
3936
3937 #ifdef HAVE_CUPS
3938         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3939                 /* Pull the location and comment strings from cups if we don't
3940                    already have one */
3941                 if ( !strlen(info->location) || !strlen(info->comment) )
3942                         cups_pull_comment_location( info );
3943         }
3944 #endif
3945
3946         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3947
3948         info->starttime = 0; /* Minutes since 12:00am GMT */
3949         info->untiltime = 0; /* Minutes since 12:00am GMT */
3950         info->priority = 1;
3951         info->default_priority = 1;
3952         info->setuptime = (uint32)time(NULL);
3953
3954         /*
3955          * I changed this as I think it is better to have a generic
3956          * DEVMODE than to crash Win2k explorer.exe   --jerry
3957          * See the HP Deskjet 990c Win2k drivers for an example.
3958          *
3959          * However the default devmode appears to cause problems
3960          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3961          * the "default devmode" parameter   --jerry 22/01/2002
3962          */
3963
3964         if (lp_default_devmode(snum)) {
3965                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3966                         goto fail;
3967                 }
3968         } else {
3969                 info->devmode = NULL;
3970         }
3971
3972         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3973                 goto fail;
3974         }
3975
3976         return WERR_OK;
3977
3978 fail:
3979         if (info->devmode)
3980                 free_nt_devicemode(&info->devmode);
3981
3982         return WERR_ACCESS_DENIED;
3983 }
3984
3985 /****************************************************************************
3986 ****************************************************************************/
3987
3988 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
3989                                 const char *servername,
3990                                 const char *sharename,
3991                                 bool get_loc_com)
3992 {
3993         int len = 0;
3994         int snum = lp_servicenumber(sharename);
3995         TDB_DATA kbuf, dbuf;
3996         fstring printername;
3997         char adevice[MAXDEVICENAME];
3998         char *comment = NULL;
3999
4000         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4001
4002         dbuf = tdb_fetch(tdb_printers, kbuf);
4003         if (!dbuf.dptr) {
4004                 return get_a_printer_2_default(info, servername,
4005                                         sharename, get_loc_com);
4006         }
4007
4008         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4009                         &info->attributes,
4010                         &info->priority,
4011                         &info->default_priority,
4012                         &info->starttime,
4013                         &info->untiltime,
4014                         &info->status,
4015                         &info->cjobs,
4016                         &info->averageppm,
4017                         &info->changeid,
4018                         &info->c_setprinter,
4019                         &info->setuptime,
4020                         info->servername,
4021                         info->printername,
4022                         info->sharename,
4023                         info->portname,
4024                         info->drivername,
4025                         &comment,
4026                         info->location,
4027                         info->sepfile,
4028                         info->printprocessor,
4029                         info->datatype,
4030                         info->parameters);
4031
4032         if (comment) {
4033                 strlcpy(info->comment, comment, sizeof(info->comment));
4034                 SAFE_FREE(comment);
4035         }
4036
4037         /* Samba has to have shared raw drivers. */
4038         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4039         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4040
4041         /* Restore the stripped strings. */
4042         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4043
4044         if ( lp_force_printername(snum) ) {
4045                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4046         } else {
4047                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4048         }
4049
4050         fstrcpy(info->printername, printername);
4051
4052 #ifdef HAVE_CUPS
4053         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4054                 /* Pull the location and comment strings from cups if we don't
4055                    already have one */
4056                 if ( !strlen(info->location) || !strlen(info->comment) )
4057                         cups_pull_comment_location( info );
4058         }
4059 #endif
4060
4061         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4062
4063         /*
4064          * Some client drivers freak out if there is a NULL devmode
4065          * (probably the driver is not checking before accessing
4066          * the devmode pointer)   --jerry
4067          *
4068          * See comments in get_a_printer_2_default()
4069          */
4070
4071         if (lp_default_devmode(snum) && !info->devmode) {
4072                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4073                         printername));
4074                 info->devmode = construct_nt_devicemode(printername);
4075         }
4076
4077         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4078         if (info->devmode) {
4079                 fstrcpy(info->devmode->devicename, adevice);
4080         }
4081
4082         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4083                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4084                 SAFE_FREE(dbuf.dptr);
4085                 return WERR_NOMEM;
4086         }
4087         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4088
4089         /* This will get the current RPC talloc context, but we should be
4090            passing this as a parameter... fixme... JRA ! */
4091
4092         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4093                 SAFE_FREE(dbuf.dptr);
4094                 return WERR_NOMEM;
4095         }
4096
4097         /* Fix for OS/2 drivers. */
4098
4099         if (get_remote_arch() == RA_OS2) {
4100                 map_to_os2_driver(info->drivername);
4101         }
4102
4103         SAFE_FREE(dbuf.dptr);
4104
4105         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4106                  sharename, info->printername, info->drivername));
4107
4108         return WERR_OK;
4109 }
4110
4111 /****************************************************************************
4112  Debugging function, dump at level 6 the struct in the logs.
4113 ****************************************************************************/
4114 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4115 {
4116         uint32 result;
4117         NT_PRINTER_INFO_LEVEL_2 *info2;
4118
4119         DEBUG(106,("Dumping printer at level [%d]\n", level));
4120
4121         switch (level) {
4122                 case 2:
4123                 {
4124                         if (printer->info_2 == NULL)
4125                                 result=5;
4126                         else
4127                         {
4128                                 info2=printer->info_2;
4129
4130                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4131                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4132                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4133                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4134                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4135                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4136                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4137                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4138                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4139                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4140                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4141
4142                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4143                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4144                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4145                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4146                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4147                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4148                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4149                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4150                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4151                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4152                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4153                                 result=0;
4154                         }
4155                         break;
4156                 }
4157                 default:
4158                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4159                         result=1;
4160                         break;
4161         }
4162
4163         return result;
4164 }
4165
4166 /****************************************************************************
4167  Update the changeid time.
4168  This is SO NASTY as some drivers need this to change, others need it
4169  static. This value will change every second, and I must hope that this
4170  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4171  UTAH ! JRA.
4172 ****************************************************************************/
4173
4174 static uint32 rev_changeid(void)
4175 {
4176         struct timeval tv;
4177
4178         get_process_uptime(&tv);
4179
4180 #if 1   /* JERRY */
4181         /* Return changeid as msec since spooler restart */
4182         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4183 #else
4184         /*
4185          * This setting seems to work well but is too untested
4186          * to replace the above calculation.  Left in for experiementation
4187          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4188          */
4189         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4190 #endif
4191 }
4192
4193
4194 /*
4195  * The function below are the high level ones.
4196  * only those ones must be called from the spoolss code.
4197  * JFM.
4198  */
4199
4200 /****************************************************************************
4201  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4202 ****************************************************************************/
4203
4204 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4205 {
4206         WERROR result;
4207
4208         dump_a_printer(printer, level);
4209
4210         switch (level) {
4211                 case 2:
4212                 {
4213                         /*
4214                          * Update the changestamp.  Emperical tests show that the
4215                          * ChangeID is always updated,but c_setprinter is
4216                          *  global spooler variable (not per printer).
4217                          */
4218
4219                         /* ChangeID **must** be increasing over the lifetime
4220                            of client's spoolss service in order for the
4221                            client's cache to show updates */
4222
4223                         printer->info_2->changeid = rev_changeid();
4224
4225                         /*
4226                          * Because one day someone will ask:
4227                          * NT->NT       An admin connection to a remote
4228                          *              printer show changes imeediately in
4229                          *              the properities dialog
4230                          *
4231                          *              A non-admin connection will only show the
4232                          *              changes after viewing the properites page
4233                          *              2 times.  Seems to be related to a
4234                          *              race condition in the client between the spooler
4235                          *              updating the local cache and the Explorer.exe GUI
4236                          *              actually displaying the properties.
4237                          *
4238                          *              This is fixed in Win2k.  admin/non-admin
4239                          *              connections both display changes immediately.
4240                          *
4241                          * 14/12/01     --jerry
4242                          */
4243
4244                         result=update_a_printer_2(printer->info_2);
4245                         break;
4246                 }
4247                 default:
4248                         result=WERR_UNKNOWN_LEVEL;
4249                         break;
4250         }
4251
4252         return result;
4253 }
4254
4255 /****************************************************************************
4256  Initialize printer devmode & data with previously saved driver init values.
4257 ****************************************************************************/
4258
4259 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4260 {
4261         int                     len = 0;
4262         char *key = NULL;
4263         TDB_DATA                dbuf;
4264         NT_PRINTER_INFO_LEVEL_2 info;
4265
4266
4267         ZERO_STRUCT(info);
4268
4269         /*
4270          * Delete any printer data 'values' already set. When called for driver
4271          * replace, there will generally be some, but during an add printer, there
4272          * should not be any (if there are delete them).
4273          */
4274
4275         if ( info_ptr->data )
4276                 delete_all_printer_data( info_ptr, "" );
4277
4278         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4279                                 info_ptr->drivername) < 0) {
4280                 return false;
4281         }
4282
4283         dbuf = tdb_fetch_bystring(tdb_drivers, key);
4284         if (!dbuf.dptr) {
4285                 /*
4286                  * When changing to a driver that has no init info in the tdb, remove
4287                  * the previous drivers init info and leave the new on blank.
4288                  */
4289                 free_nt_devicemode(&info_ptr->devmode);
4290                 SAFE_FREE(key);
4291                 return false;
4292         }
4293
4294         SAFE_FREE(key);
4295         /*
4296          * Get the saved DEVMODE..
4297          */
4298
4299         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4300
4301         /*
4302          * The saved DEVMODE contains the devicename from the printer used during
4303          * the initialization save. Change it to reflect the new printer.
4304          */
4305
4306         if ( info.devmode ) {
4307                 ZERO_STRUCT(info.devmode->devicename);
4308                 fstrcpy(info.devmode->devicename, info_ptr->printername);
4309         }
4310
4311         /*
4312          * NT/2k does not change out the entire DeviceMode of a printer
4313          * when changing the driver.  Only the driverextra, private, &
4314          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
4315          *
4316          * Later examination revealed that Windows NT/2k does reset the
4317          * the printer's device mode, bit **only** when you change a
4318          * property of the device mode such as the page orientation.
4319          * --jerry
4320          */
4321
4322
4323         /* Bind the saved DEVMODE to the new the printer */
4324
4325         free_nt_devicemode(&info_ptr->devmode);
4326         info_ptr->devmode = info.devmode;
4327
4328         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4329                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4330
4331         /* Add the printer data 'values' to the new printer */
4332
4333         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4334                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4335                 return False;
4336         }
4337
4338         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4339
4340         SAFE_FREE(dbuf.dptr);
4341
4342         return true;
4343 }
4344
4345 /****************************************************************************
4346  Initialize printer devmode & data with previously saved driver init values.
4347  When a printer is created using AddPrinter, the drivername bound to the
4348  printer is used to lookup previously saved driver initialization info, which
4349  is bound to the new printer.
4350 ****************************************************************************/
4351
4352 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4353 {
4354         bool result = False;
4355
4356         switch (level) {
4357                 case 2:
4358                         result = set_driver_init_2(printer->info_2);
4359                         break;
4360
4361                 default:
4362                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4363                                 level));
4364                         break;
4365         }
4366
4367         return result;
4368 }
4369
4370 /****************************************************************************
4371  Delete driver init data stored for a specified driver
4372 ****************************************************************************/
4373
4374 bool del_driver_init(const char *drivername)
4375 {
4376         char *key;
4377         bool ret;
4378
4379         if (!drivername || !*drivername) {
4380                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4381                 return false;
4382         }
4383
4384         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4385                 return false;
4386         }
4387
4388         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4389                                 drivername));
4390
4391         ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4392         SAFE_FREE(key);
4393         return ret;
4394 }
4395
4396 /****************************************************************************
4397  Pack up the DEVMODE and values for a printer into a 'driver init' entry
4398  in the tdb. Note: this is different from the driver entry and the printer
4399  entry. There should be a single driver init entry for each driver regardless
4400  of whether it was installed from NT or 2K. Technically, they should be
4401  different, but they work out to the same struct.
4402 ****************************************************************************/
4403
4404 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4405 {
4406         char *key = NULL;
4407         uint8 *buf;
4408         int buflen, len, ret;
4409         int retlen;
4410         TDB_DATA dbuf;
4411
4412         buf = NULL;
4413         buflen = 0;
4414
4415  again:
4416         len = 0;
4417         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4418
4419         retlen = pack_values( info->data, buf+len, buflen-len );
4420         if (retlen == -1) {
4421                 ret = -1;
4422                 goto done;
4423         }
4424         len += retlen;
4425
4426         if (buflen < len) {
4427                 buf = (uint8 *)SMB_REALLOC(buf, len);
4428                 if (!buf) {
4429                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4430                         ret = -1;
4431                         goto done;
4432                 }
4433                 buflen = len;
4434                 goto again;
4435         }
4436
4437         SAFE_FREE(key);
4438         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4439                 ret = (uint32)-1;
4440                 goto done;
4441         }
4442
4443         dbuf.dptr = buf;
4444         dbuf.dsize = len;
4445
4446         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4447
4448 done:
4449         if (ret == -1)
4450                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4451
4452         SAFE_FREE(buf);
4453
4454         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4455                  info->sharename, info->drivername));
4456
4457         return ret;
4458 }
4459
4460 /****************************************************************************
4461  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4462 ****************************************************************************/
4463
4464 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4465 {
4466         uint32 result;
4467
4468         dump_a_printer(printer, level);
4469
4470         switch (level) {
4471                 case 2:
4472                         result = update_driver_init_2(printer->info_2);
4473                         break;
4474                 default:
4475                         result = 1;
4476                         break;
4477         }
4478
4479         return result;
4480 }
4481
4482 /****************************************************************************
4483  Convert the printer data value, a REG_BINARY array, into an initialization
4484  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4485  got to keep the endians happy :).
4486 ****************************************************************************/
4487
4488 static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
4489                                 const uint8_t *data, uint32_t data_len)
4490 {
4491         struct spoolss_DeviceMode devmode;
4492         enum ndr_err_code ndr_err;
4493         DATA_BLOB blob;
4494
4495         ZERO_STRUCT(devmode);
4496
4497         blob = data_blob_const(data, data_len);
4498
4499         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
4500                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4501         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4502                 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4503                 return false;
4504         }
4505
4506         return convert_devicemode("", &devmode, &nt_devmode);
4507 }
4508
4509 /****************************************************************************
4510  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4511
4512  1. Use the driver's config DLL to this UNC printername and:
4513     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4514     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4515  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4516
4517  The last step triggers saving the "driver initialization" information for
4518  this printer into the tdb. Later, new printers that use this driver will
4519  have this initialization information bound to them. This simulates the
4520  driver initialization, as if it had run on the Samba server (as it would
4521  have done on NT).
4522
4523  The Win32 client side code requirement sucks! But until we can run arbitrary
4524  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4525
4526  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4527  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4528  about it and you will realize why.  JRR 010720
4529 ****************************************************************************/
4530
4531 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4532 {
4533         WERROR        status       = WERR_OK;
4534         TALLOC_CTX    *ctx         = NULL;
4535         NT_DEVICEMODE *nt_devmode  = NULL;
4536         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4537
4538         /*
4539          * When the DEVMODE is already set on the printer, don't try to unpack it.
4540          */
4541         DEBUG(8,("save_driver_init_2: Enter...\n"));
4542
4543         if ( !printer->info_2->devmode && data_len ) {
4544                 /*
4545                  * Set devmode on printer info, so entire printer initialization can be
4546                  * saved to tdb.
4547                  */
4548
4549                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4550                         return WERR_NOMEM;
4551
4552                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4553                         status = WERR_NOMEM;
4554                         goto done;
4555                 }
4556
4557                 ZERO_STRUCTP(nt_devmode);
4558
4559                 /*
4560                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4561                  * Convert it to to a devmode structure
4562                  */
4563                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4564                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4565                         status = WERR_INVALID_PARAM;
4566                         goto done;
4567                 }
4568
4569                 printer->info_2->devmode = nt_devmode;
4570         }
4571
4572         /*
4573          * Pack up and add (or update) the DEVMODE and any current printer data to
4574          * a 'driver init' element in the tdb
4575          *
4576          */
4577
4578         if ( update_driver_init(printer, 2) != 0 ) {
4579                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4580                 status = WERR_NOMEM;
4581                 goto done;
4582         }
4583
4584         /*
4585          * If driver initialization info was successfully saved, set the current
4586          * printer to match it. This allows initialization of the current printer
4587          * as well as the driver.
4588          */
4589         status = mod_a_printer(printer, 2);
4590         if (!W_ERROR_IS_OK(status)) {
4591                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4592                                   printer->info_2->printername));
4593         }
4594
4595   done:
4596         talloc_destroy(ctx);
4597         free_nt_devicemode( &nt_devmode );
4598
4599         printer->info_2->devmode = tmp_devmode;
4600
4601         return status;
4602 }
4603
4604 /****************************************************************************
4605  Update the driver init info (DEVMODE and specifics) for a printer
4606 ****************************************************************************/
4607
4608 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4609 {
4610         WERROR status = WERR_OK;
4611
4612         switch (level) {
4613                 case 2:
4614                         status = save_driver_init_2( printer, data, data_len );
4615                         break;
4616                 default:
4617                         status = WERR_UNKNOWN_LEVEL;
4618                         break;
4619         }
4620
4621         return status;
4622 }
4623
4624 /****************************************************************************
4625  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4626
4627  Previously the code had a memory allocation problem because it always
4628  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4629  as a long as the original handle is open.  So if the client made a lot
4630  of getprinter[data]() calls, the memory usage would climb.  Now we use
4631  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4632  still use the Printer_entry->ctx for maintaining the cache copy though
4633  since that object must live as long as the handle by definition.
4634                                                     --jerry
4635
4636 ****************************************************************************/
4637
4638 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4639                         const char *sharename, bool get_loc_com)
4640 {
4641         WERROR result;
4642         fstring servername;
4643
4644         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4645
4646         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4647                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4648                 return WERR_NOMEM;
4649         }
4650
4651         switch (level) {
4652                 case 2:
4653                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4654                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4655                                 TALLOC_FREE( *pp_printer );
4656                                 return WERR_NOMEM;
4657                         }
4658
4659                         if ( print_hnd )
4660                                 fstrcpy( servername, print_hnd->servername );
4661                         else {
4662                                 fstrcpy( servername, "%L" );
4663                                 standard_sub_basic( "", "", servername,
4664                                                     sizeof(servername)-1 );
4665                         }
4666
4667                         result = get_a_printer_2( (*pp_printer)->info_2,
4668                                         servername, sharename, get_loc_com);
4669
4670                         /* we have a new printer now.  Save it with this handle */
4671
4672                         if ( !W_ERROR_IS_OK(result) ) {
4673                                 TALLOC_FREE( *pp_printer );
4674                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4675                                         sharename, (unsigned int)level, win_errstr(result)));
4676                                 return result;
4677                         }
4678
4679                         dump_a_printer( *pp_printer, level);
4680
4681                         break;
4682
4683                 default:
4684                         TALLOC_FREE( *pp_printer );
4685                         return WERR_UNKNOWN_LEVEL;
4686         }
4687
4688         return WERR_OK;
4689 }
4690
4691 WERROR get_a_printer( Printer_entry *print_hnd,
4692                         NT_PRINTER_INFO_LEVEL **pp_printer,
4693                         uint32 level,
4694                         const char *sharename)
4695 {
4696         return get_a_printer_internal(print_hnd, pp_printer, level,
4697                                         sharename, true);
4698 }
4699
4700 WERROR get_a_printer_search( Printer_entry *print_hnd,
4701                         NT_PRINTER_INFO_LEVEL **pp_printer,
4702                         uint32 level,
4703                         const char *sharename)
4704 {
4705         return get_a_printer_internal(print_hnd, pp_printer, level,
4706                                         sharename, false);
4707 }
4708
4709 /****************************************************************************
4710  Deletes a NT_PRINTER_INFO_LEVEL struct.
4711 ****************************************************************************/
4712
4713 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4714 {
4715         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4716
4717         if ( !printer )
4718                 return 0;
4719
4720         switch (level) {
4721                 case 2:
4722                         if ( printer->info_2 )
4723                                 free_nt_printer_info_level_2(&printer->info_2);
4724                         break;
4725
4726                 default:
4727                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4728                         return 1;
4729         }
4730
4731         TALLOC_FREE(*pp_printer);
4732
4733         return 0;
4734 }
4735
4736 /****************************************************************************
4737 ****************************************************************************/
4738 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4739 {
4740         uint32 result;
4741         DEBUG(104,("adding a printer at level [%d]\n", level));
4742         dump_a_printer_driver(driver, level);
4743
4744         switch (level) {
4745                 case 3:
4746                         result=add_a_printer_driver_3(driver.info_3);
4747                         break;
4748
4749                 case 6:
4750                         result=add_a_printer_driver_6(driver.info_6);
4751                         break;
4752
4753                 default:
4754                         result=1;
4755                         break;
4756         }
4757
4758         return result;
4759 }
4760 /****************************************************************************
4761 ****************************************************************************/
4762
4763 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
4764                             const char *drivername, const char *architecture,
4765                             uint32_t version)
4766 {
4767         WERROR result;
4768
4769         switch (level) {
4770                 case 3:
4771                         /* Sometime we just want any version of the driver */
4772
4773                         if ( version == DRIVER_ANY_VERSION ) {
4774                                 /* look for Win2k first and then for NT4 */
4775                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4776                                                 architecture, 3);
4777
4778                                 if ( !W_ERROR_IS_OK(result) ) {
4779                                         result = get_a_printer_driver_3( &driver->info_3,
4780                                                         drivername, architecture, 2 );
4781                                 }
4782                         } else {
4783                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4784                                         architecture, version);
4785                         }
4786                         break;
4787
4788                 default:
4789                         result=W_ERROR(1);
4790                         break;
4791         }
4792
4793         if (W_ERROR_IS_OK(result))
4794                 dump_a_printer_driver(*driver, level);
4795
4796         return result;
4797 }
4798
4799 /****************************************************************************
4800 ****************************************************************************/
4801 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4802 {
4803         uint32 result;
4804
4805         switch (level) {
4806                 case 3:
4807                 {
4808                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4809                         if (driver.info_3 != NULL)
4810                         {
4811                                 info3=driver.info_3;
4812                                 SAFE_FREE(info3->dependentfiles);
4813                                 ZERO_STRUCTP(info3);
4814                                 SAFE_FREE(info3);
4815                                 result=0;
4816                         } else {
4817                                 result=4;
4818                         }
4819                         break;
4820                 }
4821                 case 6:
4822                 {
4823                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4824                         if (driver.info_6 != NULL) {
4825                                 info6=driver.info_6;
4826                                 SAFE_FREE(info6->dependentfiles);
4827                                 SAFE_FREE(info6->previousnames);
4828                                 ZERO_STRUCTP(info6);
4829                                 SAFE_FREE(info6);
4830                                 result=0;
4831                         } else {
4832                                 result=4;
4833                         }
4834                         break;
4835                 }
4836                 default:
4837                         result=1;
4838                         break;
4839         }
4840         return result;
4841 }
4842
4843
4844 /****************************************************************************
4845   Determine whether or not a particular driver is currently assigned
4846   to a printer
4847 ****************************************************************************/
4848
4849 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4850 {
4851         int snum;
4852         int n_services = lp_numservices();
4853         NT_PRINTER_INFO_LEVEL *printer = NULL;
4854         bool in_use = False;
4855
4856         if ( !info_3 )
4857                 return False;
4858
4859         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4860
4861         /* loop through the printers.tdb and check for the drivername */
4862
4863         for (snum=0; snum<n_services && !in_use; snum++) {
4864                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4865                         continue;
4866
4867                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4868                         continue;
4869
4870                 if ( strequal(info_3->name, printer->info_2->drivername) )
4871                         in_use = True;
4872
4873                 free_a_printer( &printer, 2 );
4874         }
4875
4876         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4877
4878         if ( in_use ) {
4879                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4880                 WERROR werr;
4881
4882                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4883
4884                 /* we can still remove the driver if there is one of
4885                    "Windows NT x86" version 2 or 3 left */
4886
4887                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4888                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4889                 }
4890                 else {
4891                         switch ( info_3->cversion ) {
4892                         case 2:
4893                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4894                                 break;
4895                         case 3:
4896                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4897                                 break;
4898                         default:
4899                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4900                                         info_3->cversion));
4901                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4902                                 break;
4903                         }
4904                 }
4905
4906                 /* now check the error code */
4907
4908                 if ( W_ERROR_IS_OK(werr) ) {
4909                         /* it's ok to remove the driver, we have other architctures left */
4910                         in_use = False;
4911                         free_a_printer_driver( d, 3 );
4912                 }
4913         }
4914
4915         /* report that the driver is not in use by default */
4916
4917         return in_use;
4918 }
4919
4920
4921 /**********************************************************************
4922  Check to see if a ogiven file is in use by *info
4923  *********************************************************************/
4924
4925 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4926 {
4927         int i = 0;
4928
4929         if ( !info )
4930                 return False;
4931
4932         /* mz: skip files that are in the list but already deleted */
4933         if (!file || !file[0]) {
4934                 return false;
4935         }
4936
4937         if ( strequal(file, info->driverpath) )
4938                 return True;
4939
4940         if ( strequal(file, info->datafile) )
4941                 return True;
4942
4943         if ( strequal(file, info->configfile) )
4944                 return True;
4945
4946         if ( strequal(file, info->helpfile) )
4947                 return True;
4948
4949         /* see of there are any dependent files to examine */
4950
4951         if ( !info->dependentfiles )
4952                 return False;
4953
4954         while ( *info->dependentfiles[i] ) {
4955                 if ( strequal(file, info->dependentfiles[i]) )
4956                         return True;
4957                 i++;
4958         }
4959
4960         return False;
4961
4962 }
4963
4964 /**********************************************************************
4965  Utility function to remove the dependent file pointed to by the
4966  input parameter from the list
4967  *********************************************************************/
4968
4969 static void trim_dependent_file( fstring files[], int idx )
4970 {
4971
4972         /* bump everything down a slot */
4973
4974         while( *files[idx+1] ) {
4975                 fstrcpy( files[idx], files[idx+1] );
4976                 idx++;
4977         }
4978
4979         *files[idx] = '\0';
4980
4981         return;
4982 }
4983
4984 /**********************************************************************
4985  Check if any of the files used by src are also used by drv
4986  *********************************************************************/
4987
4988 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4989                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4990 {
4991         bool    in_use = False;
4992         int     i = 0;
4993
4994         if ( !src || !drv )
4995                 return False;
4996
4997         /* check each file.  Remove it from the src structure if it overlaps */
4998
4999         if ( drv_file_in_use(src->driverpath, drv) ) {
5000                 in_use = True;
5001                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
5002                 fstrcpy( src->driverpath, "" );
5003         }
5004
5005         if ( drv_file_in_use(src->datafile, drv) ) {
5006                 in_use = True;
5007                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
5008                 fstrcpy( src->datafile, "" );
5009         }
5010
5011         if ( drv_file_in_use(src->configfile, drv) ) {
5012                 in_use = True;
5013                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5014                 fstrcpy( src->configfile, "" );
5015         }
5016
5017         if ( drv_file_in_use(src->helpfile, drv) ) {
5018                 in_use = True;
5019                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5020                 fstrcpy( src->helpfile, "" );
5021         }
5022
5023         /* are there any dependentfiles to examine? */
5024
5025         if ( !src->dependentfiles )
5026                 return in_use;
5027
5028         while ( *src->dependentfiles[i] ) {
5029                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5030                         in_use = True;
5031                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5032                         trim_dependent_file( src->dependentfiles, i );
5033                 } else
5034                         i++;
5035         }
5036
5037         return in_use;
5038 }
5039
5040 /****************************************************************************
5041   Determine whether or not a particular driver files are currently being
5042   used by any other driver.
5043
5044   Return value is True if any files were in use by other drivers
5045   and False otherwise.
5046
5047   Upon return, *info has been modified to only contain the driver files
5048   which are not in use
5049
5050   Fix from mz:
5051
5052   This needs to check all drivers to ensure that all files in use
5053   have been removed from *info, not just the ones in the first
5054   match.
5055 ****************************************************************************/
5056
5057 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5058 {
5059         int                             i;
5060         int                             ndrivers;
5061         uint32                          version;
5062         fstring                         *list = NULL;
5063         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5064         bool in_use = false;
5065
5066         if ( !info )
5067                 return False;
5068
5069         version = info->cversion;
5070
5071         /* loop over all driver versions */
5072
5073         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5074
5075         /* get the list of drivers */
5076
5077         list = NULL;
5078         ndrivers = get_ntdrivers(&list, info->environment, version);
5079
5080         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5081                 ndrivers, info->environment, version));
5082
5083         /* check each driver for overlap in files */
5084
5085         for (i=0; i<ndrivers; i++) {
5086                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5087
5088                 ZERO_STRUCT(driver);
5089
5090                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5091                         SAFE_FREE(list);
5092                         return True;
5093                 }
5094
5095                 /* check if d2 uses any files from d1 */
5096                 /* only if this is a different driver than the one being deleted */
5097
5098                 if ( !strequal(info->name, driver.info_3->name) ) {
5099                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
5100                                 /* mz: Do not instantly return -
5101                                  * we need to ensure this file isn't
5102                                  * also in use by other drivers. */
5103                                 in_use = true;
5104                         }
5105                 }
5106
5107                 free_a_printer_driver(driver, 3);
5108         }
5109
5110         SAFE_FREE(list);
5111
5112         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5113
5114         driver.info_3 = info;
5115
5116         if ( DEBUGLEVEL >= 20 )
5117                 dump_a_printer_driver( driver, 3 );
5118
5119         return in_use;
5120 }
5121
5122 /****************************************************************************
5123   Actually delete the driver files.  Make sure that
5124   printer_driver_files_in_use() return False before calling
5125   this.
5126 ****************************************************************************/
5127
5128 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5129                                 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
5130 {
5131         int i = 0;
5132         char *s;
5133         const char *file;
5134         connection_struct *conn;
5135         NTSTATUS nt_status;
5136         SMB_STRUCT_STAT  st;
5137         char *oldcwd;
5138         fstring printdollar;
5139         int printdollar_snum;
5140         bool ret = false;
5141
5142         if ( !info_3 )
5143                 return False;
5144
5145         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5146
5147         fstrcpy(printdollar, "print$");
5148
5149         printdollar_snum = find_service(printdollar);
5150         if (printdollar_snum == -1) {
5151                 return false;
5152         }
5153
5154         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5155                                        lp_pathname(printdollar_snum),
5156                                        rpc_pipe->server_info, &oldcwd);
5157         if (!NT_STATUS_IS_OK(nt_status)) {
5158                 DEBUG(0,("delete_driver_files: create_conn_struct "
5159                          "returned %s\n", nt_errstr(nt_status)));
5160                 return false;
5161         }
5162
5163         if ( !CAN_WRITE(conn) ) {
5164                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5165                 goto fail;
5166         }
5167
5168         /* now delete the files; must strip the '\print$' string from
5169            fron of path                                                */
5170
5171         if ( *info_3->driverpath ) {
5172                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5173                         file = s;
5174                         driver_unix_convert(conn,file,&st);
5175                         DEBUG(10,("deleting driverfile [%s]\n", s));
5176                         unlink_internals(conn, NULL, 0, file, False);
5177                 }
5178         }
5179
5180         if ( *info_3->configfile ) {
5181                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5182                         file = s;
5183                         driver_unix_convert(conn,file,&st);
5184                         DEBUG(10,("deleting configfile [%s]\n", s));
5185                         unlink_internals(conn, NULL, 0, file, False);
5186                 }
5187         }
5188
5189         if ( *info_3->datafile ) {
5190                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5191                         file = s;
5192                         driver_unix_convert(conn,file,&st);
5193                         DEBUG(10,("deleting datafile [%s]\n", s));
5194                         unlink_internals(conn, NULL, 0, file, False);
5195                 }
5196         }
5197
5198         if ( *info_3->helpfile ) {
5199                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5200                         file = s;
5201                         driver_unix_convert(conn,file,&st);
5202                         DEBUG(10,("deleting helpfile [%s]\n", s));
5203                         unlink_internals(conn, NULL, 0, file, False);
5204                 }
5205         }
5206
5207         /* check if we are done removing files */
5208
5209         if ( info_3->dependentfiles ) {
5210                 while ( info_3->dependentfiles[i][0] ) {
5211                         char *p;
5212
5213                         /* bypass the "\print$" portion of the path */
5214
5215                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5216                                 file = p;
5217                                 driver_unix_convert(conn,file,&st);
5218                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5219                                 unlink_internals(conn, NULL, 0, file, False);
5220                         }
5221
5222                         i++;
5223                 }
5224         }
5225
5226         goto done;
5227  fail:
5228         ret = false;
5229  done:
5230         if (conn != NULL) {
5231                 vfs_ChDir(conn, oldcwd);
5232                 conn_free_internal(conn);
5233         }
5234         return ret;
5235 }
5236
5237 /****************************************************************************
5238  Remove a printer driver from the TDB.  This assumes that the the driver was
5239  previously looked up.
5240  ***************************************************************************/
5241
5242 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5243                              NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3,
5244                              uint32 version, bool delete_files )
5245 {
5246         char *key = NULL;
5247         const char     *arch;
5248         TDB_DATA        dbuf;
5249         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
5250
5251         /* delete the tdb data first */
5252
5253         arch = get_short_archi(info_3->environment);
5254         if (!arch) {
5255                 return WERR_UNKNOWN_PRINTER_DRIVER;
5256         }
5257         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5258                         arch, version, info_3->name) < 0) {
5259                 return WERR_NOMEM;
5260         }
5261
5262         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5263                 key, delete_files ? "TRUE" : "FALSE" ));
5264
5265         ctr.info_3 = info_3;
5266         dump_a_printer_driver( ctr, 3 );
5267
5268         /* check if the driver actually exists for this environment */
5269
5270         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5271         if ( !dbuf.dptr ) {
5272                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5273                 SAFE_FREE(key);
5274                 return WERR_UNKNOWN_PRINTER_DRIVER;
5275         }
5276
5277         SAFE_FREE( dbuf.dptr );
5278
5279         /* ok... the driver exists so the delete should return success */
5280
5281         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5282                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5283                 SAFE_FREE(key);
5284                 return WERR_ACCESS_DENIED;
5285         }
5286
5287         /*
5288          * now delete any associated files if delete_files == True
5289          * even if this part failes, we return succes because the
5290          * driver doesn not exist any more
5291          */
5292
5293         if ( delete_files )
5294                 delete_driver_files(rpc_pipe, info_3);
5295
5296         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5297         SAFE_FREE(key);
5298
5299         return WERR_OK;
5300 }
5301
5302 /****************************************************************************
5303  Store a security desc for a printer.
5304 ****************************************************************************/
5305
5306 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5307 {
5308         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5309         SEC_DESC_BUF *old_secdesc_ctr = NULL;
5310         TALLOC_CTX *mem_ctx = NULL;
5311         TDB_DATA kbuf;
5312         TDB_DATA dbuf;
5313         DATA_BLOB blob;
5314         WERROR status;
5315         NTSTATUS nt_status;
5316
5317         mem_ctx = talloc_init("nt_printing_setsec");
5318         if (mem_ctx == NULL)
5319                 return WERR_NOMEM;
5320
5321         /* The old owner and group sids of the security descriptor are not
5322            present when new ACEs are added or removed by changing printer
5323            permissions through NT.  If they are NULL in the new security
5324            descriptor then copy them over from the old one. */
5325
5326         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5327                 DOM_SID *owner_sid, *group_sid;
5328                 SEC_ACL *dacl, *sacl;
5329                 SEC_DESC *psd = NULL;
5330                 size_t size;
5331
5332                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5333                         status = WERR_NOMEM;
5334                         goto out;
5335                 }
5336
5337                 /* Pick out correct owner and group sids */
5338
5339                 owner_sid = secdesc_ctr->sd->owner_sid ?
5340                         secdesc_ctr->sd->owner_sid :
5341                         old_secdesc_ctr->sd->owner_sid;
5342
5343                 group_sid = secdesc_ctr->sd->group_sid ?
5344                         secdesc_ctr->sd->group_sid :
5345                         old_secdesc_ctr->sd->group_sid;
5346
5347                 dacl = secdesc_ctr->sd->dacl ?
5348                         secdesc_ctr->sd->dacl :
5349                         old_secdesc_ctr->sd->dacl;
5350
5351                 sacl = secdesc_ctr->sd->sacl ?
5352                         secdesc_ctr->sd->sacl :
5353                         old_secdesc_ctr->sd->sacl;
5354
5355                 /* Make a deep copy of the security descriptor */
5356
5357                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5358                                     owner_sid, group_sid,
5359                                     sacl,
5360                                     dacl,
5361                                     &size);
5362
5363                 if (!psd) {
5364                         status = WERR_NOMEM;
5365                         goto out;
5366                 }
5367
5368                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5369         }
5370
5371         if (!new_secdesc_ctr) {
5372                 new_secdesc_ctr = secdesc_ctr;
5373         }
5374
5375         /* Store the security descriptor in a tdb */
5376
5377         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5378                                           &blob.data, &blob.length);
5379         if (!NT_STATUS_IS_OK(nt_status)) {
5380                 status = ntstatus_to_werror(nt_status);
5381                 goto out;
5382         }
5383
5384         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5385
5386         dbuf.dptr = (unsigned char *)blob.data;
5387         dbuf.dsize = blob.length;
5388
5389         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5390                 status = WERR_OK;
5391         } else {
5392                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5393                 status = WERR_BADFUNC;
5394         }
5395
5396         /* Free malloc'ed memory */
5397         talloc_free(blob.data);
5398
5399  out:
5400
5401         if (mem_ctx)
5402                 talloc_destroy(mem_ctx);
5403         return status;
5404 }
5405
5406 /****************************************************************************
5407  Construct a default security descriptor buffer for a printer.
5408 ****************************************************************************/
5409
5410 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5411 {
5412         SEC_ACE ace[5]; /* max number of ace entries */
5413         int i = 0;
5414         uint32_t sa;
5415         SEC_ACL *psa = NULL;
5416         SEC_DESC_BUF *sdb = NULL;
5417         SEC_DESC *psd = NULL;
5418         DOM_SID adm_sid;
5419         size_t sd_size;
5420
5421         /* Create an ACE where Everyone is allowed to print */
5422
5423         sa = PRINTER_ACE_PRINT;
5424         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5425                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5426
5427         /* Add the domain admins group if we are a DC */
5428
5429         if ( IS_DC ) {
5430                 DOM_SID domadmins_sid;
5431
5432                 sid_copy(&domadmins_sid, get_global_sam_sid());
5433                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5434
5435                 sa = PRINTER_ACE_FULL_CONTROL;
5436                 init_sec_ace(&ace[i++], &domadmins_sid,
5437                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5438                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5439                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5440                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5441         }
5442         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5443                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5444
5445                 sa = PRINTER_ACE_FULL_CONTROL;
5446                 init_sec_ace(&ace[i++], &adm_sid,
5447                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5448                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5449                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5450                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5451         }
5452
5453         /* add BUILTIN\Administrators as FULL CONTROL */
5454
5455         sa = PRINTER_ACE_FULL_CONTROL;
5456         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5457                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5458                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5459         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5460                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5461                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5462
5463         /* Make the security descriptor owned by the BUILTIN\Administrators */
5464
5465         /* The ACL revision number in rpc_secdesc.h differs from the one
5466            created by NT when setting ACE entries in printer
5467            descriptors.  NT4 complains about the property being edited by a
5468            NT5 machine. */
5469
5470         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5471                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5472                         &global_sid_Builtin_Administrators,
5473                         &global_sid_Builtin_Administrators,
5474                         NULL, psa, &sd_size);
5475         }
5476
5477         if (!psd) {
5478                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5479                 return NULL;
5480         }
5481
5482         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5483
5484         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5485                  (unsigned int)sd_size));
5486
5487         return sdb;
5488 }
5489
5490 /****************************************************************************
5491  Get a security desc for a printer.
5492 ****************************************************************************/
5493
5494 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5495 {
5496         TDB_DATA kbuf;
5497         TDB_DATA dbuf;
5498         DATA_BLOB blob;
5499         char *temp;
5500         NTSTATUS status;
5501
5502         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5503                 sharename = temp + 1;
5504         }
5505
5506         /* Fetch security descriptor from tdb */
5507
5508         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5509
5510         dbuf = tdb_fetch(tdb_printers, kbuf);
5511         if (dbuf.dptr) {
5512
5513                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5514                                                  secdesc_ctr);
5515                 SAFE_FREE(dbuf.dptr);
5516
5517                 if (NT_STATUS_IS_OK(status)) {
5518                         return true;
5519                 }
5520         }
5521
5522         *secdesc_ctr = construct_default_printer_sdb(ctx);
5523         if (!*secdesc_ctr) {
5524                 return false;
5525         }
5526
5527         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5528                                        &blob.data, &blob.length);
5529         if (NT_STATUS_IS_OK(status)) {
5530                 dbuf.dptr = (unsigned char *)blob.data;
5531                 dbuf.dsize = blob.length;
5532                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5533                 talloc_free(blob.data);
5534         }
5535
5536         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5537            this security descriptor has been created when winbindd was
5538            down.  Take ownership of security descriptor. */
5539
5540         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5541                 DOM_SID owner_sid;
5542
5543                 /* Change sd owner to workgroup administrator */
5544
5545                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5546                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5547                         SEC_DESC *psd = NULL;
5548                         size_t size;
5549
5550                         /* Create new sd */
5551
5552                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5553
5554                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5555                                             &owner_sid,
5556                                             (*secdesc_ctr)->sd->group_sid,
5557                                             (*secdesc_ctr)->sd->sacl,
5558                                             (*secdesc_ctr)->sd->dacl,
5559                                             &size);
5560
5561                         if (!psd) {
5562                                 return False;
5563                         }
5564
5565                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5566                         if (!new_secdesc_ctr) {
5567                                 return False;
5568                         }
5569
5570                         /* Swap with other one */
5571
5572                         *secdesc_ctr = new_secdesc_ctr;
5573
5574                         /* Set it */
5575
5576                         nt_printing_setsec(sharename, *secdesc_ctr);
5577                 }
5578         }
5579
5580         if (DEBUGLEVEL >= 10) {
5581                 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5582                 int i;
5583
5584                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5585                            sharename, the_acl->num_aces));
5586
5587                 for (i = 0; i < the_acl->num_aces; i++) {
5588                         DEBUG(10, ("%s %d %d 0x%08x\n",
5589                                    sid_string_dbg(&the_acl->aces[i].trustee),
5590                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5591                                    the_acl->aces[i].access_mask));
5592                 }
5593         }
5594
5595         return True;
5596 }
5597
5598 /* error code:
5599         0: everything OK
5600         1: level not implemented
5601         2: file doesn't exist
5602         3: can't allocate memory
5603         4: can't free memory
5604         5: non existant struct
5605 */
5606
5607 /*
5608         A printer and a printer driver are 2 different things.
5609         NT manages them separatelly, Samba does the same.
5610         Why ? Simply because it's easier and it makes sense !
5611
5612         Now explanation: You have 3 printers behind your samba server,
5613         2 of them are the same make and model (laser A and B). But laser B
5614         has an 3000 sheet feeder and laser A doesn't such an option.
5615         Your third printer is an old dot-matrix model for the accounting :-).
5616
5617         If the /usr/local/samba/lib directory (default dir), you will have
5618         5 files to describe all of this.
5619
5620         3 files for the printers (1 by printer):
5621                 NTprinter_laser A
5622                 NTprinter_laser B
5623                 NTprinter_accounting
5624         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5625                 NTdriver_printer model X
5626                 NTdriver_printer model Y
5627
5628 jfm: I should use this comment for the text file to explain
5629         same thing for the forms BTW.
5630         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5631
5632 */
5633
5634 /* Convert generic access rights to printer object specific access rights.
5635    It turns out that NT4 security descriptors use generic access rights and
5636    NT5 the object specific ones. */
5637
5638 void map_printer_permissions(SEC_DESC *sd)
5639 {
5640         int i;
5641
5642         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5643                 se_map_generic(&sd->dacl->aces[i].access_mask,
5644                                &printer_generic_mapping);
5645         }
5646 }
5647
5648 void map_job_permissions(SEC_DESC *sd)
5649 {
5650         int i;
5651
5652         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5653                 se_map_generic(&sd->dacl->aces[i].access_mask,
5654                                &job_generic_mapping);
5655         }
5656 }
5657
5658
5659 /****************************************************************************
5660  Check a user has permissions to perform the given operation.  We use the
5661  permission constants defined in include/rpc_spoolss.h to check the various
5662  actions we perform when checking printer access.
5663
5664    PRINTER_ACCESS_ADMINISTER:
5665        print_queue_pause, print_queue_resume, update_printer_sec,
5666        update_printer, spoolss_addprinterex_level_2,
5667        _spoolss_setprinterdata
5668
5669    PRINTER_ACCESS_USE:
5670        print_job_start
5671
5672    JOB_ACCESS_ADMINISTER:
5673        print_job_delete, print_job_pause, print_job_resume,
5674        print_queue_purge
5675
5676   Try access control in the following order (for performance reasons):
5677     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
5678     2)  check security descriptor (bit comparisons in memory)
5679     3)  "printer admins" (may result in numerous calls to winbind)
5680
5681  ****************************************************************************/
5682 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5683                         int access_type)
5684 {
5685         SEC_DESC_BUF *secdesc = NULL;
5686         uint32 access_granted;
5687         NTSTATUS status;
5688         const char *pname;
5689         TALLOC_CTX *mem_ctx = NULL;
5690         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5691
5692         /* If user is NULL then use the current_user structure */
5693
5694         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5695
5696         if (server_info->utok.uid == sec_initial_uid()
5697             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5698                 return True;
5699         }
5700
5701         /* Get printer name */
5702
5703         pname = PRINTERNAME(snum);
5704
5705         if (!pname || !*pname) {
5706                 errno = EACCES;
5707                 return False;
5708         }
5709
5710         /* Get printer security descriptor */
5711
5712         if(!(mem_ctx = talloc_init("print_access_check"))) {
5713                 errno = ENOMEM;
5714                 return False;
5715         }
5716
5717         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5718                 talloc_destroy(mem_ctx);
5719                 errno = ENOMEM;
5720                 return False;
5721         }
5722
5723         if (access_type == JOB_ACCESS_ADMINISTER) {
5724                 SEC_DESC_BUF *parent_secdesc = secdesc;
5725
5726                 /* Create a child security descriptor to check permissions
5727                    against.  This is because print jobs are child objects
5728                    objects of a printer. */
5729
5730                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5731
5732                 if (!NT_STATUS_IS_OK(status)) {
5733                         talloc_destroy(mem_ctx);
5734                         errno = map_errno_from_nt_status(status);
5735                         return False;
5736                 }
5737
5738                 map_job_permissions(secdesc->sd);
5739         } else {
5740                 map_printer_permissions(secdesc->sd);
5741         }
5742
5743         /* Check access */
5744         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5745                                  &access_granted);
5746
5747         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5748
5749         /* see if we need to try the printer admin list */
5750
5751         if ((access_granted == 0) &&
5752             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5753                                          NULL, NULL, server_info->ptok,
5754                                          lp_printer_admin(snum)))) {
5755                 talloc_destroy(mem_ctx);
5756                 return True;
5757         }
5758
5759         talloc_destroy(mem_ctx);
5760
5761         if (!NT_STATUS_IS_OK(status)) {
5762                 errno = EACCES;
5763         }
5764
5765         return NT_STATUS_IS_OK(status);
5766 }
5767
5768 /****************************************************************************
5769  Check the time parameters allow a print operation.
5770 *****************************************************************************/
5771
5772 bool print_time_access_check(const char *servicename)
5773 {
5774         NT_PRINTER_INFO_LEVEL *printer = NULL;
5775         bool ok = False;
5776         time_t now = time(NULL);
5777         struct tm *t;
5778         uint32 mins;
5779
5780         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5781                 return False;
5782
5783         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5784                 ok = True;
5785
5786         t = gmtime(&now);
5787         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5788
5789         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5790                 ok = True;
5791
5792         free_a_printer(&printer, 2);
5793
5794         if (!ok)
5795                 errno = EACCES;
5796
5797         return ok;
5798 }
5799
5800 /****************************************************************************
5801  Fill in the servername sent in the _spoolss_open_printer_ex() call
5802 ****************************************************************************/
5803
5804 char* get_server_name( Printer_entry *printer )
5805 {
5806         return printer->servername;
5807 }
5808
5809