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