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