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