Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ira/wip.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23
24 static TDB_CONTEXT *tdb_forms; /* used for forms files */
25 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
26 static TDB_CONTEXT *tdb_printers; /* used for printers files */
27
28 #define FORMS_PREFIX "FORMS/"
29 #define DRIVERS_PREFIX "DRIVERS/"
30 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
31 #define PRINTERS_PREFIX "PRINTERS/"
32 #define SECDESC_PREFIX "SECDESC/"
33 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
34
35 #define NTDRIVERS_DATABASE_VERSION_1 1
36 #define NTDRIVERS_DATABASE_VERSION_2 2
37 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
38 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
39 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
40
41 /* Map generic permissions to printer object specific permissions */
42
43 const struct generic_mapping printer_generic_mapping = {
44         PRINTER_READ,
45         PRINTER_WRITE,
46         PRINTER_EXECUTE,
47         PRINTER_ALL_ACCESS
48 };
49
50 const struct standard_mapping printer_std_mapping = {
51         PRINTER_READ,
52         PRINTER_WRITE,
53         PRINTER_EXECUTE,
54         PRINTER_ALL_ACCESS
55 };
56
57 /* Map generic permissions to print server object specific permissions */
58
59 const struct generic_mapping printserver_generic_mapping = {
60         SERVER_READ,
61         SERVER_WRITE,
62         SERVER_EXECUTE,
63         SERVER_ALL_ACCESS
64 };
65
66 const struct generic_mapping printserver_std_mapping = {
67         SERVER_READ,
68         SERVER_WRITE,
69         SERVER_EXECUTE,
70         SERVER_ALL_ACCESS
71 };
72
73 /* Map generic permissions to job object specific permissions */
74
75 const struct generic_mapping job_generic_mapping = {
76         JOB_READ,
77         JOB_WRITE,
78         JOB_EXECUTE,
79         JOB_ALL_ACCESS
80 };
81
82 /* We need one default form to support our default printer. Msoft adds the
83 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
84 array index). Letter is always first, so (for the current code) additions
85 always put things in the correct order. */
86 static const nt_forms_struct default_forms[] = {
87         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
88         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
89         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
90         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
91         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
92         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
93         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
94         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
95         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
96         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
97         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
98         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
99         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
100         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
101         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
102         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
103         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
104         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
105         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
106         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
107         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
108         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
109         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
110         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
111         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
112         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
113         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
114         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
115         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
116         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
117         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
118         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
119         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
120         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
121         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
122         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
123         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
124         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
125         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
126         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
127         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
128         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
129         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
130         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
131         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
132         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
133         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
134         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
135         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
136         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
138         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
139         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
140         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
141         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
142         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
143         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
144         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
145         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
146         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
147         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
148         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
149         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
150         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
151         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
152         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
153         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
154         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
155         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
156         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
157         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
158         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
159         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
160         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
161         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
162         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
163         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
164         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
165         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
166         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
167         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
168         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
169         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
170         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
171         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
172         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
173         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
174         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
175         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
176         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
177         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
178         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
179         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
180         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
181         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
182         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
183         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
184         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
185         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
186         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
187         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
188         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
189         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
190         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
191         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
192         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
193         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
194         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
195         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
196         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
197         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
198         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
199         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
200         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
201         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
202         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
203         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
204         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
205 };
206
207 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      = 0x0401;
2677         nt_devmode->driverversion    = 0x0400;
2678         nt_devmode->size             = 0x00DC;
2679         nt_devmode->driverextra      = 0x0000;
2680         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2681                                        DEFAULTSOURCE | COPIES | SCALE |
2682                                        PAPERSIZE | ORIENTATION;
2683         nt_devmode->orientation      = 1;
2684         nt_devmode->papersize        = PAPER_LETTER;
2685         nt_devmode->paperlength      = 0;
2686         nt_devmode->paperwidth       = 0;
2687         nt_devmode->scale            = 0x64;
2688         nt_devmode->copies           = 1;
2689         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2690         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2691         nt_devmode->color            = COLOR_MONOCHROME;
2692         nt_devmode->duplex           = DUP_SIMPLEX;
2693         nt_devmode->yresolution      = 0;
2694         nt_devmode->ttoption         = TT_SUBDEV;
2695         nt_devmode->collate          = COLLATE_FALSE;
2696         nt_devmode->icmmethod        = 0;
2697         nt_devmode->icmintent        = 0;
2698         nt_devmode->mediatype        = 0;
2699         nt_devmode->dithertype       = 0;
2700
2701         /* non utilisés par un driver d'imprimante */
2702         nt_devmode->logpixels        = 0;
2703         nt_devmode->bitsperpel       = 0;
2704         nt_devmode->pelswidth        = 0;
2705         nt_devmode->pelsheight       = 0;
2706         nt_devmode->displayflags     = 0;
2707         nt_devmode->displayfrequency = 0;
2708         nt_devmode->reserved1        = 0;
2709         nt_devmode->reserved2        = 0;
2710         nt_devmode->panningwidth     = 0;
2711         nt_devmode->panningheight    = 0;
2712
2713         nt_devmode->nt_dev_private = NULL;
2714         return nt_devmode;
2715 }
2716
2717 /****************************************************************************
2718  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2719 ****************************************************************************/
2720
2721 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2722 {
2723         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2724
2725         if(nt_devmode == NULL)
2726                 return;
2727
2728         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2729
2730         SAFE_FREE(nt_devmode->nt_dev_private);
2731         SAFE_FREE(*devmode_ptr);
2732 }
2733
2734 /****************************************************************************
2735  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2736 ****************************************************************************/
2737
2738 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2739 {
2740         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2741
2742         if ( !info )
2743                 return;
2744
2745         free_nt_devicemode(&info->devmode);
2746
2747         TALLOC_FREE( *info_ptr );
2748 }
2749
2750
2751 /****************************************************************************
2752 ****************************************************************************/
2753 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2754 {
2755         int len = 0;
2756         int extra_len = 0;
2757         NT_DEVICEMODE devmode;
2758
2759         ZERO_STRUCT(devmode);
2760
2761         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2762
2763         if (!*nt_devmode) return len;
2764
2765         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2766                           devmode.devicename,
2767                           devmode.formname,
2768
2769                           &devmode.specversion,
2770                           &devmode.driverversion,
2771                           &devmode.size,
2772                           &devmode.driverextra,
2773                           &devmode.orientation,
2774                           &devmode.papersize,
2775                           &devmode.paperlength,
2776                           &devmode.paperwidth,
2777                           &devmode.scale,
2778                           &devmode.copies,
2779                           &devmode.defaultsource,
2780                           &devmode.printquality,
2781                           &devmode.color,
2782                           &devmode.duplex,
2783                           &devmode.yresolution,
2784                           &devmode.ttoption,
2785                           &devmode.collate,
2786                           &devmode.logpixels,
2787
2788                           &devmode.fields,
2789                           &devmode.bitsperpel,
2790                           &devmode.pelswidth,
2791                           &devmode.pelsheight,
2792                           &devmode.displayflags,
2793                           &devmode.displayfrequency,
2794                           &devmode.icmmethod,
2795                           &devmode.icmintent,
2796                           &devmode.mediatype,
2797                           &devmode.dithertype,
2798                           &devmode.reserved1,
2799                           &devmode.reserved2,
2800                           &devmode.panningwidth,
2801                           &devmode.panningheight,
2802                           &devmode.nt_dev_private);
2803
2804         if (devmode.nt_dev_private) {
2805                 /* the len in tdb_unpack is an int value and
2806                  * devmode.driverextra is only a short
2807                  */
2808                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2809                 devmode.driverextra=(uint16)extra_len;
2810
2811                 /* check to catch an invalid TDB entry so we don't segfault */
2812                 if (devmode.driverextra == 0) {
2813                         devmode.nt_dev_private = NULL;
2814                 }
2815         }
2816
2817         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2818         if (!*nt_devmode) {
2819                 SAFE_FREE(devmode.nt_dev_private);
2820                 return -1;
2821         }
2822
2823         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2824         if (devmode.nt_dev_private)
2825                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2826
2827         return len;
2828 }
2829
2830 /****************************************************************************
2831  Allocate and initialize a new slot.
2832 ***************************************************************************/
2833
2834 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2835 {
2836         NT_PRINTER_KEY  *d;
2837         int             key_index;
2838
2839         if ( !name || !data )
2840                 return -1;
2841
2842         /* allocate another slot in the NT_PRINTER_KEY array */
2843
2844         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2845                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2846                 return -1;
2847         }
2848
2849         data->keys = d;
2850
2851         key_index = data->num_keys;
2852
2853         /* initialze new key */
2854
2855         data->keys[key_index].name = talloc_strdup( data, name );
2856
2857         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
2858                 return -1;
2859
2860         data->num_keys++;
2861
2862         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2863
2864         return key_index;
2865 }
2866
2867 /****************************************************************************
2868  search for a registry key name in the existing printer data
2869  ***************************************************************************/
2870
2871 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2872 {
2873         int i;
2874
2875         for ( i=0; i<data->num_keys; i++ ) {
2876                 if ( strequal( data->keys[i].name, name ) ) {
2877
2878                         /* cleanup memory */
2879
2880                         TALLOC_FREE( data->keys[i].name );
2881                         TALLOC_FREE( data->keys[i].values );
2882
2883                         /* if not the end of the array, move remaining elements down one slot */
2884
2885                         data->num_keys--;
2886                         if ( data->num_keys && (i < data->num_keys) )
2887                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2888
2889                         break;
2890                 }
2891         }
2892
2893
2894         return data->num_keys;
2895 }
2896
2897 /****************************************************************************
2898  search for a registry key name in the existing printer data
2899  ***************************************************************************/
2900
2901 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2902 {
2903         int             key_index = -1;
2904         int             i;
2905
2906         if ( !data || !name )
2907                 return -1;
2908
2909         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2910
2911         /* loop over all existing keys */
2912
2913         for ( i=0; i<data->num_keys; i++ ) {
2914                 if ( strequal(data->keys[i].name, name) ) {
2915                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2916                         key_index = i;
2917                         break;
2918
2919                 }
2920         }
2921
2922         return key_index;
2923 }
2924
2925 /****************************************************************************
2926  ***************************************************************************/
2927
2928 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2929 {
2930         int     i, j;
2931         int     key_len;
2932         int     num_subkeys = 0;
2933         char    *p;
2934         fstring *subkeys_ptr = NULL;
2935         fstring subkeyname;
2936
2937         *subkeys = NULL;
2938
2939         if ( !data )
2940                 return 0;
2941
2942         if ( !key )
2943                 return -1;
2944
2945         /* special case of asking for the top level printer data registry key names */
2946
2947         if ( strlen(key) == 0 ) {
2948                 for ( i=0; i<data->num_keys; i++ ) {
2949
2950                         /* found a match, so allocate space and copy the name */
2951
2952                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2953                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2954                                         num_subkeys+1));
2955                                 return -1;
2956                         }
2957
2958                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2959                         num_subkeys++;
2960                 }
2961
2962                 goto done;
2963         }
2964
2965         /* asking for the subkeys of some key */
2966         /* subkey paths are stored in the key name using '\' as the delimiter */
2967
2968         for ( i=0; i<data->num_keys; i++ ) {
2969                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2970
2971                         /* if we found the exact key, then break */
2972                         key_len = strlen( key );
2973                         if ( strlen(data->keys[i].name) == key_len )
2974                                 break;
2975
2976                         /* get subkey path */
2977
2978                         p = data->keys[i].name + key_len;
2979                         if ( *p == '\\' )
2980                                 p++;
2981                         fstrcpy( subkeyname, p );
2982                         if ( (p = strchr( subkeyname, '\\' )) )
2983                                 *p = '\0';
2984
2985                         /* don't add a key more than once */
2986
2987                         for ( j=0; j<num_subkeys; j++ ) {
2988                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2989                                         break;
2990                         }
2991
2992                         if ( j != num_subkeys )
2993                                 continue;
2994
2995                         /* found a match, so allocate space and copy the name */
2996
2997                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2998                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2999                                         num_subkeys+1));
3000                                 return 0;
3001                         }
3002
3003                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3004                         num_subkeys++;
3005                 }
3006
3007         }
3008
3009         /* return error if the key was not found */
3010
3011         if ( i == data->num_keys ) {
3012                 SAFE_FREE(subkeys_ptr);
3013                 return -1;
3014         }
3015
3016 done:
3017         /* tag off the end */
3018
3019         if (num_subkeys)
3020                 fstrcpy(subkeys_ptr[num_subkeys], "" );
3021
3022         *subkeys = subkeys_ptr;
3023
3024         return num_subkeys;
3025 }
3026
3027 #ifdef HAVE_ADS
3028 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3029                             const char *sz)
3030 {
3031         smb_ucs2_t conv_str[1024];
3032         size_t str_size;
3033
3034         regval_ctr_delvalue(ctr, val_name);
3035         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
3036                              STR_TERMINATE | STR_NOALIGN);
3037         regval_ctr_addvalue(ctr, val_name, REG_SZ,
3038                             (char *) conv_str, str_size);
3039 }
3040
3041 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3042                                uint32 dword)
3043 {
3044         regval_ctr_delvalue(ctr, val_name);
3045         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3046                             (char *) &dword, sizeof(dword));
3047 }
3048
3049 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3050                               bool b)
3051 {
3052         uint8 bin_bool = (b ? 1 : 0);
3053         regval_ctr_delvalue(ctr, val_name);
3054         regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3055                             (char *) &bin_bool, sizeof(bin_bool));
3056 }
3057
3058 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3059                                          const char *multi_sz)
3060 {
3061         smb_ucs2_t *conv_strs = NULL;
3062         size_t str_size;
3063
3064         /* a multi-sz has to have a null string terminator, i.e., the last
3065            string must be followed by two nulls */
3066         str_size = strlen(multi_sz) + 2;
3067         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
3068         if (!conv_strs) {
3069                 return;
3070         }
3071
3072         /* Change to byte units. */
3073         str_size *= sizeof(smb_ucs2_t);
3074         push_ucs2(NULL, conv_strs, multi_sz, str_size,
3075                   STR_TERMINATE | STR_NOALIGN);
3076
3077         regval_ctr_delvalue(ctr, val_name);
3078         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
3079                             (char *) conv_strs, str_size);
3080         SAFE_FREE(conv_strs);
3081 }
3082
3083 /****************************************************************************
3084  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3085  *
3086  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3087  * @return bool indicating success or failure
3088  ***************************************************************************/
3089
3090 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3091 {
3092         struct regval_ctr *ctr = NULL;
3093         fstring longname;
3094         const char *dnssuffix;
3095         char *allocated_string = NULL;
3096         const char *ascii_str;
3097         int i;
3098
3099         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3100                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3101         ctr = info2->data->keys[i].values;
3102
3103         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3104         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3105
3106         /* we make the assumption that the netbios name is the same
3107            as the DNS name sinc ethe former will be what we used to
3108            join the domain */
3109
3110         dnssuffix = get_mydnsdomname(talloc_tos());
3111         if (dnssuffix && *dnssuffix) {
3112                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3113         } else {
3114                 fstrcpy( longname, global_myname() );
3115         }
3116
3117         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3118
3119         if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3120                 return false;
3121         }
3122         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3123         SAFE_FREE(allocated_string);
3124
3125         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3126         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3127         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3128         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3129         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3130         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3131         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3132         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3133         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3134
3135         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3136                           (info2->attributes &
3137                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3138
3139         switch (info2->attributes & 0x3) {
3140         case 0:
3141                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3142                 break;
3143         case 1:
3144                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3145                 break;
3146         case 2:
3147                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3148                 break;
3149         default:
3150                 ascii_str = "unknown";
3151         }
3152         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3153
3154         return True;
3155 }
3156
3157 /*****************************************************************
3158  ****************************************************************/
3159
3160 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3161                                struct GUID guid)
3162 {
3163         int i;
3164         struct regval_ctr *ctr=NULL;
3165         UNISTR2 unistr_guid;
3166
3167         /* find the DsSpooler key */
3168         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3169                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3170         ctr = info2->data->keys[i].values;
3171
3172         regval_ctr_delvalue(ctr, "objectGUID");
3173
3174         /* We used to store this as a REG_BINARY but that causes
3175            Vista to whine */
3176
3177         ZERO_STRUCT( unistr_guid );
3178
3179         init_unistr2( &unistr_guid, GUID_string(talloc_tos(), &guid),
3180                       UNI_STR_TERMINATE );
3181
3182         regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3183                             (char *)unistr_guid.buffer,
3184                             unistr_guid.uni_max_len*2);
3185
3186 }
3187
3188 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3189                                      NT_PRINTER_INFO_LEVEL *printer)
3190 {
3191         ADS_STATUS ads_rc;
3192         LDAPMessage *res;
3193         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3194         char *srv_dn_utf8, **srv_cn_utf8;
3195         TALLOC_CTX *ctx;
3196         ADS_MODLIST mods;
3197         const char *attrs[] = {"objectGUID", NULL};
3198         struct GUID guid;
3199         WERROR win_rc = WERR_OK;
3200         size_t converted_size;
3201
3202         /* build the ads mods */
3203         ctx = talloc_init("nt_printer_publish_ads");
3204         if (ctx == NULL) {
3205                 return WERR_NOMEM;
3206         }
3207
3208         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3209
3210         /* figure out where to publish */
3211         ads_find_machine_acct(ads, &res, global_myname());
3212
3213         /* We use ldap_get_dn here as we need the answer
3214          * in utf8 to call ldap_explode_dn(). JRA. */
3215
3216         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3217         if (!srv_dn_utf8) {
3218                 TALLOC_FREE(ctx);
3219                 return WERR_SERVER_UNAVAILABLE;
3220         }
3221         ads_msgfree(ads, res);
3222         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3223         if (!srv_cn_utf8) {
3224                 TALLOC_FREE(ctx);
3225                 ldap_memfree(srv_dn_utf8);
3226                 return WERR_SERVER_UNAVAILABLE;
3227         }
3228         /* Now convert to CH_UNIX. */
3229         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3230                 TALLOC_FREE(ctx);
3231                 ldap_memfree(srv_dn_utf8);
3232                 ldap_memfree(srv_cn_utf8);
3233                 return WERR_SERVER_UNAVAILABLE;
3234         }
3235         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3236                 TALLOC_FREE(ctx);
3237                 ldap_memfree(srv_dn_utf8);
3238                 ldap_memfree(srv_cn_utf8);
3239                 TALLOC_FREE(srv_dn);
3240                 return WERR_SERVER_UNAVAILABLE;
3241         }
3242
3243         ldap_memfree(srv_dn_utf8);
3244         ldap_memfree(srv_cn_utf8);
3245
3246         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3247         if (!srv_cn_escaped) {
3248                 TALLOC_FREE(ctx);
3249                 return WERR_SERVER_UNAVAILABLE;
3250         }
3251         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3252         if (!sharename_escaped) {
3253                 SAFE_FREE(srv_cn_escaped);
3254                 TALLOC_FREE(ctx);
3255                 return WERR_SERVER_UNAVAILABLE;
3256         }
3257
3258         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3259
3260         SAFE_FREE(srv_cn_escaped);
3261         SAFE_FREE(sharename_escaped);
3262
3263         mods = ads_init_mods(ctx);
3264
3265         if (mods == NULL) {
3266                 SAFE_FREE(prt_dn);
3267                 TALLOC_FREE(ctx);
3268                 return WERR_NOMEM;
3269         }
3270
3271         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3272         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3273                     printer->info_2->sharename);
3274
3275         /* publish it */
3276         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3277         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3278                 int i;
3279                 for (i=0; mods[i] != 0; i++)
3280                         ;
3281                 mods[i] = (LDAPMod *)-1;
3282                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3283         }
3284
3285         if (!ADS_ERR_OK(ads_rc))
3286                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3287
3288         /* retreive the guid and store it locally */
3289         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3290                 ZERO_STRUCT(guid);
3291                 ads_pull_guid(ads, res, &guid);
3292                 ads_msgfree(ads, res);
3293                 store_printer_guid(printer->info_2, guid);
3294                 win_rc = mod_a_printer(printer, 2);
3295         }
3296         TALLOC_FREE(ctx);
3297
3298         return win_rc;
3299 }
3300
3301 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3302                                        NT_PRINTER_INFO_LEVEL *printer)
3303 {
3304         ADS_STATUS ads_rc;
3305         LDAPMessage *res = NULL;
3306         char *prt_dn = NULL;
3307
3308         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3309
3310         /* remove the printer from the directory */
3311         ads_rc = ads_find_printer_on_server(ads, &res,
3312                             printer->info_2->sharename, global_myname());
3313
3314         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3315                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3316                 if (!prt_dn) {
3317                         ads_msgfree(ads, res);
3318                         return WERR_NOMEM;
3319                 }
3320                 ads_rc = ads_del_dn(ads, prt_dn);
3321                 TALLOC_FREE(prt_dn);
3322         }
3323
3324         if (res) {
3325                 ads_msgfree(ads, res);
3326         }
3327         return WERR_OK;
3328 }
3329
3330 /****************************************************************************
3331  * Publish a printer in the directory
3332  *
3333  * @param snum describing printer service
3334  * @return WERROR indicating status of publishing
3335  ***************************************************************************/
3336
3337 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3338 {
3339         ADS_STATUS ads_rc;
3340         ADS_STRUCT *ads = NULL;
3341         NT_PRINTER_INFO_LEVEL *printer = NULL;
3342         WERROR win_rc;
3343
3344         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3345         if (!W_ERROR_IS_OK(win_rc))
3346                 goto done;
3347
3348         switch (action) {
3349         case DSPRINT_PUBLISH:
3350         case DSPRINT_UPDATE:
3351                 /* set the DsSpooler info and attributes */
3352                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3353                         win_rc = WERR_NOMEM;
3354                         goto done;
3355                 }
3356
3357                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3358                 break;
3359         case DSPRINT_UNPUBLISH:
3360                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3361                 break;
3362         default:
3363                 win_rc = WERR_NOT_SUPPORTED;
3364                 goto done;
3365         }
3366
3367         win_rc = mod_a_printer(printer, 2);
3368         if (!W_ERROR_IS_OK(win_rc)) {
3369                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3370                 goto done;
3371         }
3372
3373         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3374         if (!ads) {
3375                 DEBUG(3, ("ads_init() failed\n"));
3376                 win_rc = WERR_SERVER_UNAVAILABLE;
3377                 goto done;
3378         }
3379         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3380         SAFE_FREE(ads->auth.password);
3381         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3382                 NULL, NULL);
3383
3384         /* ads_connect() will find the DC for us */
3385         ads_rc = ads_connect(ads);
3386         if (!ADS_ERR_OK(ads_rc)) {
3387                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3388                 win_rc = WERR_ACCESS_DENIED;
3389                 goto done;
3390         }
3391
3392         switch (action) {
3393         case DSPRINT_PUBLISH:
3394         case DSPRINT_UPDATE:
3395                 win_rc = nt_printer_publish_ads(ads, printer);
3396                 break;
3397         case DSPRINT_UNPUBLISH:
3398                 win_rc = nt_printer_unpublish_ads(ads, printer);
3399                 break;
3400         }
3401
3402 done:
3403         free_a_printer(&printer, 2);
3404         ads_destroy(&ads);
3405         return win_rc;
3406 }
3407
3408 WERROR check_published_printers(void)
3409 {
3410         ADS_STATUS ads_rc;
3411         ADS_STRUCT *ads = NULL;
3412         int snum;
3413         int n_services = lp_numservices();
3414         NT_PRINTER_INFO_LEVEL *printer = NULL;
3415
3416         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3417         if (!ads) {
3418                 DEBUG(3, ("ads_init() failed\n"));
3419                 return WERR_SERVER_UNAVAILABLE;
3420         }
3421         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3422         SAFE_FREE(ads->auth.password);
3423         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3424                 NULL, NULL);
3425
3426         /* ads_connect() will find the DC for us */
3427         ads_rc = ads_connect(ads);
3428         if (!ADS_ERR_OK(ads_rc)) {
3429                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3430                 ads_destroy(&ads);
3431                 ads_kdestroy("MEMORY:prtpub_cache");
3432                 return WERR_ACCESS_DENIED;
3433         }
3434
3435         for (snum = 0; snum < n_services; snum++) {
3436                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3437                         continue;
3438
3439                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3440                                                 lp_servicename(snum))) &&
3441                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3442                         nt_printer_publish_ads(ads, printer);
3443
3444                 free_a_printer(&printer, 2);
3445         }
3446
3447         ads_destroy(&ads);
3448         ads_kdestroy("MEMORY:prtpub_cache");
3449         return WERR_OK;
3450 }
3451
3452 bool is_printer_published(Printer_entry *print_hnd, int snum,
3453                           struct GUID *guid)
3454 {
3455         NT_PRINTER_INFO_LEVEL *printer = NULL;
3456         struct regval_ctr *ctr;
3457         struct regval_blob *guid_val;
3458         WERROR win_rc;
3459         int i;
3460         bool ret = False;
3461
3462         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3463
3464         if (!W_ERROR_IS_OK(win_rc) ||
3465             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3466             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3467             !(ctr = printer->info_2->data->keys[i].values) ||
3468             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3469         {
3470                 free_a_printer(&printer, 2);
3471                 return False;
3472         }
3473
3474         /* fetching printer guids really ought to be a separate function. */
3475
3476         if ( guid ) {
3477                 fstring guid_str;
3478
3479                 /* We used to store the guid as REG_BINARY, then swapped
3480                    to REG_SZ for Vista compatibility so check for both */
3481
3482                 switch ( regval_type(guid_val) ){
3483                 case REG_SZ:
3484                         rpcstr_pull( guid_str, regval_data_p(guid_val),
3485                                      sizeof(guid_str)-1, -1, STR_TERMINATE );
3486                         ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3487                         break;
3488                 case REG_BINARY:
3489                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3490                                 ret = False;
3491                                 break;
3492                         }
3493                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3494                         break;
3495                 default:
3496                         DEBUG(0,("is_printer_published: GUID value stored as "
3497                                  "invaluid type (%d)\n", regval_type(guid_val) ));
3498                         break;
3499                 }
3500         }
3501
3502         free_a_printer(&printer, 2);
3503         return ret;
3504 }
3505 #else
3506 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3507 {
3508         return WERR_OK;
3509 }
3510
3511 WERROR check_published_printers(void)
3512 {
3513         return WERR_OK;
3514 }
3515
3516 bool is_printer_published(Printer_entry *print_hnd, int snum,
3517                           struct GUID *guid)
3518 {
3519         return False;
3520 }
3521 #endif /* HAVE_ADS */
3522
3523 /****************************************************************************
3524  ***************************************************************************/
3525
3526 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3527 {
3528         NT_PRINTER_DATA *data;
3529         int             i;
3530         int             removed_keys = 0;
3531         int             empty_slot;
3532
3533         data = p2->data;
3534         empty_slot = data->num_keys;
3535
3536         if ( !key )
3537                 return WERR_INVALID_PARAM;
3538
3539         /* remove all keys */
3540
3541         if ( !strlen(key) ) {
3542
3543                 TALLOC_FREE( data );
3544
3545                 p2->data = NULL;
3546
3547                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3548                         p2->printername ));
3549
3550                 return WERR_OK;
3551         }
3552
3553         /* remove a specific key (and all subkeys) */
3554
3555         for ( i=0; i<data->num_keys; i++ ) {
3556                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3557                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3558                                 data->keys[i].name));
3559
3560                         TALLOC_FREE( data->keys[i].name );
3561                         TALLOC_FREE( data->keys[i].values );
3562
3563                         /* mark the slot as empty */
3564
3565                         ZERO_STRUCTP( &data->keys[i] );
3566                 }
3567         }
3568
3569         /* find the first empty slot */
3570
3571         for ( i=0; i<data->num_keys; i++ ) {
3572                 if ( !data->keys[i].name ) {
3573                         empty_slot = i;
3574                         removed_keys++;
3575                         break;
3576                 }
3577         }
3578
3579         if ( i == data->num_keys )
3580                 /* nothing was removed */
3581                 return WERR_INVALID_PARAM;
3582
3583         /* move everything down */
3584
3585         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3586                 if ( data->keys[i].name ) {
3587                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3588                         ZERO_STRUCTP( &data->keys[i] );
3589                         empty_slot++;
3590                         removed_keys++;
3591                 }
3592         }
3593
3594         /* update count */
3595
3596         data->num_keys -= removed_keys;
3597
3598         /* sanity check to see if anything is left */
3599
3600         if ( !data->num_keys ) {
3601                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3602
3603                 SAFE_FREE( data->keys );
3604                 ZERO_STRUCTP( data );
3605         }
3606
3607         return WERR_OK;
3608 }
3609
3610 /****************************************************************************
3611  ***************************************************************************/
3612
3613 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3614 {
3615         WERROR          result = WERR_OK;
3616         int             key_index;
3617
3618         /* we must have names on non-zero length */
3619
3620         if ( !key || !*key|| !value || !*value )
3621                 return WERR_INVALID_NAME;
3622
3623         /* find the printer key first */
3624
3625         key_index = lookup_printerkey( p2->data, key );
3626         if ( key_index == -1 )
3627                 return WERR_OK;
3628
3629         /* make sure the value exists so we can return the correct error code */
3630
3631         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3632                 return WERR_BADFILE;
3633
3634         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3635
3636         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3637                 key, value ));
3638
3639         return result;
3640 }
3641
3642 /****************************************************************************
3643  ***************************************************************************/
3644
3645 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3646                            uint32 type, uint8 *data, int real_len )
3647 {
3648         WERROR          result = WERR_OK;
3649         int             key_index;
3650
3651         /* we must have names on non-zero length */
3652
3653         if ( !key || !*key|| !value || !*value )
3654                 return WERR_INVALID_NAME;
3655
3656         /* find the printer key first */
3657
3658         key_index = lookup_printerkey( p2->data, key );
3659         if ( key_index == -1 )
3660                 key_index = add_new_printer_key( p2->data, key );
3661
3662         if ( key_index == -1 )
3663                 return WERR_NOMEM;
3664
3665         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3666                 type, (const char *)data, real_len );
3667
3668         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3669                 key, value, type, real_len  ));
3670
3671         return result;
3672 }
3673
3674 /****************************************************************************
3675  ***************************************************************************/
3676
3677 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3678 {
3679         int             key_index;
3680
3681         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3682                 return NULL;
3683
3684         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3685                 key, value ));
3686
3687         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3688 }
3689
3690 /****************************************************************************
3691  Unpack a list of registry values frem the TDB
3692  ***************************************************************************/
3693
3694 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3695 {
3696         int             len = 0;
3697         uint32          type;
3698         fstring string;
3699         const char *valuename = NULL;
3700         const char *keyname = NULL;
3701         char            *str;
3702         int             size;
3703         uint8           *data_p;
3704         struct regval_blob      *regval_p;
3705         int             key_index;
3706
3707         /* add the "PrinterDriverData" key first for performance reasons */
3708
3709         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3710
3711         /* loop and unpack the rest of the registry values */
3712
3713         while ( True ) {
3714
3715                 /* check to see if there are any more registry values */
3716
3717                 regval_p = NULL;
3718                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3719                 if ( !regval_p )
3720                         break;
3721
3722                 /* unpack the next regval */
3723
3724                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3725                                   string,
3726                                   &type,
3727                                   &size,
3728                                   &data_p);
3729
3730                 /* lookup for subkey names which have a type of REG_NONE */
3731                 /* there's no data with this entry */
3732
3733                 if ( type == REG_NONE ) {
3734                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3735                                 add_new_printer_key( printer_data, string );
3736                         continue;
3737                 }
3738
3739                 /*
3740                  * break of the keyname from the value name.
3741                  * Valuenames can have embedded '\'s so be careful.
3742                  * only support one level of keys.  See the
3743                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3744                  * -- jerry
3745                  */
3746
3747                 str = strchr_m( string, '\\');
3748
3749                 /* Put in "PrinterDriverData" is no key specified */
3750
3751                 if ( !str ) {
3752                         keyname = SPOOL_PRINTERDATA_KEY;
3753                         valuename = string;
3754                 }
3755                 else {
3756                         *str = '\0';
3757                         keyname = string;
3758                         valuename = str+1;
3759                 }
3760
3761                 /* see if we need a new key */
3762
3763                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3764                         key_index = add_new_printer_key( printer_data, keyname );
3765
3766                 if ( key_index == -1 ) {
3767                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3768                                 keyname));
3769                         break;
3770                 }
3771
3772                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3773
3774                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3775                    Thanks to Martin Zielinski for the hint. */
3776
3777                 if ( type == REG_BINARY &&
3778                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3779                      strequal( valuename, "objectGUID" ) )
3780                 {
3781                         struct GUID guid;
3782                         UNISTR2 unistr_guid;
3783
3784                         ZERO_STRUCT( unistr_guid );
3785
3786                         /* convert the GUID to a UNICODE string */
3787
3788                         memcpy( &guid, data_p, sizeof(struct GUID) );
3789
3790                         init_unistr2( &unistr_guid,
3791                                       GUID_string(talloc_tos(), &guid),
3792                                       UNI_STR_TERMINATE );
3793
3794                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3795                                              valuename, REG_SZ,
3796                                              (const char *)unistr_guid.buffer,
3797                                              unistr_guid.uni_str_len*2 );
3798
3799                 } else {
3800                         /* add the value */
3801
3802                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3803                                              valuename, type, (const char *)data_p,
3804                                              size );
3805                 }
3806
3807                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3808
3809         }
3810
3811         return len;
3812 }
3813
3814 /****************************************************************************
3815  ***************************************************************************/
3816
3817 static char *last_from;
3818 static char *last_to;
3819
3820 static const char *get_last_from(void)
3821 {
3822         if (!last_from) {
3823                 return "";
3824         }
3825         return last_from;
3826 }
3827
3828 static const char *get_last_to(void)
3829 {
3830         if (!last_to) {
3831                 return "";
3832         }
3833         return last_to;
3834 }
3835
3836 static bool set_last_from_to(const char *from, const char *to)
3837 {
3838         char *orig_from = last_from;
3839         char *orig_to = last_to;
3840
3841         last_from = SMB_STRDUP(from);
3842         last_to = SMB_STRDUP(to);
3843
3844         SAFE_FREE(orig_from);
3845         SAFE_FREE(orig_to);
3846
3847         if (!last_from || !last_to) {
3848                 SAFE_FREE(last_from);
3849                 SAFE_FREE(last_to);
3850                 return false;
3851         }
3852         return true;
3853 }
3854
3855 static void map_to_os2_driver(fstring drivername)
3856 {
3857         char *mapfile = lp_os2_driver_map();
3858         char **lines = NULL;
3859         int numlines = 0;
3860         int i;
3861
3862         if (!strlen(drivername))
3863                 return;
3864
3865         if (!*mapfile)
3866                 return;
3867
3868         if (strequal(drivername,get_last_from())) {
3869                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3870                         drivername,get_last_to()));
3871                 fstrcpy(drivername,get_last_to());
3872                 return;
3873         }
3874
3875         lines = file_lines_load(mapfile, &numlines,0,NULL);
3876         if (numlines == 0 || lines == NULL) {
3877                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3878                 TALLOC_FREE(lines);
3879                 return;
3880         }
3881
3882         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3883
3884         for( i = 0; i < numlines; i++) {
3885                 char *nt_name = lines[i];
3886                 char *os2_name = strchr(nt_name,'=');
3887
3888                 if (!os2_name)
3889                         continue;
3890
3891                 *os2_name++ = 0;
3892
3893                 while (isspace(*nt_name))
3894                         nt_name++;
3895
3896                 if (!*nt_name || strchr("#;",*nt_name))
3897                         continue;
3898
3899                 {
3900                         int l = strlen(nt_name);
3901                         while (l && isspace(nt_name[l-1])) {
3902                                 nt_name[l-1] = 0;
3903                                 l--;
3904                         }
3905                 }
3906
3907                 while (isspace(*os2_name))
3908                         os2_name++;
3909
3910                 {
3911                         int l = strlen(os2_name);
3912                         while (l && isspace(os2_name[l-1])) {
3913                                 os2_name[l-1] = 0;
3914                                 l--;
3915                         }
3916                 }
3917
3918                 if (strequal(nt_name,drivername)) {
3919                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3920                         set_last_from_to(drivername,os2_name);
3921                         fstrcpy(drivername,os2_name);
3922                         TALLOC_FREE(lines);
3923                         return;
3924                 }
3925         }
3926
3927         TALLOC_FREE(lines);
3928 }
3929
3930 /****************************************************************************
3931  Get a default printer info 2 struct.
3932 ****************************************************************************/
3933
3934 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3935                                 const char *servername,
3936                                 const char* sharename,
3937                                 bool get_loc_com)
3938 {
3939         int snum = lp_servicenumber(sharename);
3940
3941         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3942         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3943                 servername, sharename);
3944         fstrcpy(info->sharename, sharename);
3945         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3946
3947         /* by setting the driver name to an empty string, a local NT admin
3948            can now run the **local** APW to install a local printer driver
3949            for a Samba shared printer in 2.2.  Without this, drivers **must** be
3950            installed on the Samba server for NT clients --jerry */
3951 #if 0   /* JERRY --do not uncomment-- */
3952         if (!*info->drivername)
3953                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3954 #endif
3955
3956
3957         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3958
3959         strlcpy(info->comment, "", sizeof(info->comment));
3960         fstrcpy(info->printprocessor, "winprint");
3961         fstrcpy(info->datatype, "RAW");
3962
3963 #ifdef HAVE_CUPS
3964         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3965                 /* Pull the location and comment strings from cups if we don't
3966                    already have one */
3967                 if ( !strlen(info->location) || !strlen(info->comment) )
3968                         cups_pull_comment_location( info );
3969         }
3970 #endif
3971
3972         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3973
3974         info->starttime = 0; /* Minutes since 12:00am GMT */
3975         info->untiltime = 0; /* Minutes since 12:00am GMT */
3976         info->priority = 1;
3977         info->default_priority = 1;
3978         info->setuptime = (uint32)time(NULL);
3979
3980         /*
3981          * I changed this as I think it is better to have a generic
3982          * DEVMODE than to crash Win2k explorer.exe   --jerry
3983          * See the HP Deskjet 990c Win2k drivers for an example.
3984          *
3985          * However the default devmode appears to cause problems
3986          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3987          * the "default devmode" parameter   --jerry 22/01/2002
3988          */
3989
3990         if (lp_default_devmode(snum)) {
3991                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3992                         goto fail;
3993                 }
3994         } else {
3995                 info->devmode = NULL;
3996         }
3997
3998         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3999                 goto fail;
4000         }
4001
4002         return WERR_OK;
4003
4004 fail:
4005         if (info->devmode)
4006                 free_nt_devicemode(&info->devmode);
4007
4008         return WERR_ACCESS_DENIED;
4009 }
4010
4011 /****************************************************************************
4012 ****************************************************************************/
4013
4014 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4015                                 const char *servername,
4016                                 const char *sharename,
4017                                 bool get_loc_com)
4018 {
4019         int len = 0;
4020         int snum = lp_servicenumber(sharename);
4021         TDB_DATA kbuf, dbuf;
4022         fstring printername;
4023         char adevice[MAXDEVICENAME];
4024         char *comment = NULL;
4025
4026         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4027
4028         dbuf = tdb_fetch(tdb_printers, kbuf);
4029         if (!dbuf.dptr) {
4030                 return get_a_printer_2_default(info, servername,
4031                                         sharename, get_loc_com);
4032         }
4033
4034         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4035                         &info->attributes,
4036                         &info->priority,
4037                         &info->default_priority,
4038                         &info->starttime,
4039                         &info->untiltime,
4040                         &info->status,
4041                         &info->cjobs,
4042                         &info->averageppm,
4043                         &info->changeid,
4044                         &info->c_setprinter,
4045                         &info->setuptime,
4046                         info->servername,
4047                         info->printername,
4048                         info->sharename,
4049                         info->portname,
4050                         info->drivername,
4051                         &comment,
4052                         info->location,
4053                         info->sepfile,
4054                         info->printprocessor,
4055                         info->datatype,
4056                         info->parameters);
4057
4058         if (comment) {
4059                 strlcpy(info->comment, comment, sizeof(info->comment));
4060                 SAFE_FREE(comment);
4061         }
4062
4063         /* Samba has to have shared raw drivers. */
4064         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4065         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4066
4067         /* Restore the stripped strings. */
4068         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4069
4070         if ( lp_force_printername(snum) ) {
4071                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4072         } else {
4073                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4074         }
4075
4076         fstrcpy(info->printername, printername);
4077
4078 #ifdef HAVE_CUPS
4079         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4080                 /* Pull the location and comment strings from cups if we don't
4081                    already have one */
4082                 if ( !strlen(info->location) || !strlen(info->comment) )
4083                         cups_pull_comment_location( info );
4084         }
4085 #endif
4086
4087         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4088
4089         /*
4090          * Some client drivers freak out if there is a NULL devmode
4091          * (probably the driver is not checking before accessing
4092          * the devmode pointer)   --jerry
4093          *
4094          * See comments in get_a_printer_2_default()
4095          */
4096
4097         if (lp_default_devmode(snum) && !info->devmode) {
4098                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4099                         printername));
4100                 info->devmode = construct_nt_devicemode(printername);
4101         }
4102
4103         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4104         if (info->devmode) {
4105                 fstrcpy(info->devmode->devicename, adevice);
4106         }
4107
4108         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4109                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4110                 SAFE_FREE(dbuf.dptr);
4111                 return WERR_NOMEM;
4112         }
4113         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4114
4115         /* This will get the current RPC talloc context, but we should be
4116            passing this as a parameter... fixme... JRA ! */
4117
4118         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4119                 SAFE_FREE(dbuf.dptr);
4120                 return WERR_NOMEM;
4121         }
4122
4123         /* Fix for OS/2 drivers. */
4124
4125         if (get_remote_arch() == RA_OS2) {
4126                 map_to_os2_driver(info->drivername);
4127         }
4128
4129         SAFE_FREE(dbuf.dptr);
4130
4131         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4132                  sharename, info->printername, info->drivername));
4133
4134         return WERR_OK;
4135 }
4136
4137 /****************************************************************************
4138  Debugging function, dump at level 6 the struct in the logs.
4139 ****************************************************************************/
4140 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4141 {
4142         uint32 result;
4143         NT_PRINTER_INFO_LEVEL_2 *info2;
4144
4145         DEBUG(106,("Dumping printer at level [%d]\n", level));
4146
4147         switch (level) {
4148                 case 2:
4149                 {
4150                         if (printer->info_2 == NULL)
4151                                 result=5;
4152                         else
4153                         {
4154                                 info2=printer->info_2;
4155
4156                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4157                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4158                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4159                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4160                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4161                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4162                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4163                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4164                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4165                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4166                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4167
4168                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4169                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4170                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4171                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4172                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4173                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4174                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4175                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4176                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4177                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4178                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4179                                 result=0;
4180                         }
4181                         break;
4182                 }
4183                 default:
4184                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4185                         result=1;
4186                         break;
4187         }
4188
4189         return result;
4190 }
4191
4192 /****************************************************************************
4193  Update the changeid time.
4194  This is SO NASTY as some drivers need this to change, others need it
4195  static. This value will change every second, and I must hope that this
4196  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4197  UTAH ! JRA.
4198 ****************************************************************************/
4199
4200 static uint32 rev_changeid(void)
4201 {
4202         struct timeval tv;
4203
4204         get_process_uptime(&tv);
4205
4206 #if 1   /* JERRY */
4207         /* Return changeid as msec since spooler restart */
4208         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4209 #else
4210         /*
4211          * This setting seems to work well but is too untested
4212          * to replace the above calculation.  Left in for experiementation
4213          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4214          */
4215         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4216 #endif
4217 }
4218
4219
4220 /*
4221  * The function below are the high level ones.
4222  * only those ones must be called from the spoolss code.
4223  * JFM.
4224  */
4225
4226 /****************************************************************************
4227  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4228 ****************************************************************************/
4229
4230 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4231 {
4232         WERROR result;
4233
4234         dump_a_printer(printer, level);
4235
4236         switch (level) {
4237                 case 2:
4238                 {
4239                         /*
4240                          * Update the changestamp.  Emperical tests show that the
4241                          * ChangeID is always updated,but c_setprinter is
4242                          *  global spooler variable (not per printer).
4243                          */
4244
4245                         /* ChangeID **must** be increasing over the lifetime
4246                            of client's spoolss service in order for the
4247                            client's cache to show updates */
4248
4249                         printer->info_2->changeid = rev_changeid();
4250
4251                         /*
4252                          * Because one day someone will ask:
4253                          * NT->NT       An admin connection to a remote
4254                          *              printer show changes imeediately in
4255                          *              the properities dialog
4256                          *
4257                          *              A non-admin connection will only show the
4258                          *              changes after viewing the properites page
4259                          *              2 times.  Seems to be related to a
4260                          *              race condition in the client between the spooler
4261                          *              updating the local cache and the Explorer.exe GUI
4262                          *              actually displaying the properties.
4263                          *
4264                          *              This is fixed in Win2k.  admin/non-admin
4265                          *              connections both display changes immediately.
4266                          *
4267                          * 14/12/01     --jerry
4268                          */
4269
4270                         result=update_a_printer_2(printer->info_2);
4271                         break;
4272                 }
4273                 default:
4274                         result=WERR_UNKNOWN_LEVEL;
4275                         break;
4276         }
4277
4278         return result;
4279 }
4280
4281 /****************************************************************************
4282  Initialize printer devmode & data with previously saved driver init values.
4283 ****************************************************************************/
4284
4285 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4286 {
4287         int                     len = 0;
4288         char *key = NULL;
4289         TDB_DATA                dbuf;
4290         NT_PRINTER_INFO_LEVEL_2 info;
4291
4292
4293         ZERO_STRUCT(info);
4294
4295         /*
4296          * Delete any printer data 'values' already set. When called for driver
4297          * replace, there will generally be some, but during an add printer, there
4298          * should not be any (if there are delete them).
4299          */
4300
4301         if ( info_ptr->data )
4302                 delete_all_printer_data( info_ptr, "" );
4303
4304         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4305                                 info_ptr->drivername) < 0) {
4306                 return false;
4307         }
4308
4309         dbuf = tdb_fetch_bystring(tdb_drivers, key);
4310         if (!dbuf.dptr) {
4311                 /*
4312                  * When changing to a driver that has no init info in the tdb, remove
4313                  * the previous drivers init info and leave the new on blank.
4314                  */
4315                 free_nt_devicemode(&info_ptr->devmode);
4316                 SAFE_FREE(key);
4317                 return false;
4318         }
4319
4320         SAFE_FREE(key);
4321         /*
4322          * Get the saved DEVMODE..
4323          */
4324
4325         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4326
4327         /*
4328          * The saved DEVMODE contains the devicename from the printer used during
4329          * the initialization save. Change it to reflect the new printer.
4330          */
4331
4332         if ( info.devmode ) {
4333                 ZERO_STRUCT(info.devmode->devicename);
4334                 fstrcpy(info.devmode->devicename, info_ptr->printername);
4335         }
4336
4337         /*
4338          * NT/2k does not change out the entire DeviceMode of a printer
4339          * when changing the driver.  Only the driverextra, private, &
4340          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
4341          *
4342          * Later examination revealed that Windows NT/2k does reset the
4343          * the printer's device mode, bit **only** when you change a
4344          * property of the device mode such as the page orientation.
4345          * --jerry
4346          */
4347
4348
4349         /* Bind the saved DEVMODE to the new the printer */
4350
4351         free_nt_devicemode(&info_ptr->devmode);
4352         info_ptr->devmode = info.devmode;
4353
4354         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4355                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4356
4357         /* Add the printer data 'values' to the new printer */
4358
4359         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4360                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4361                 return False;
4362         }
4363
4364         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4365
4366         SAFE_FREE(dbuf.dptr);
4367
4368         return true;
4369 }
4370
4371 /****************************************************************************
4372  Initialize printer devmode & data with previously saved driver init values.
4373  When a printer is created using AddPrinter, the drivername bound to the
4374  printer is used to lookup previously saved driver initialization info, which
4375  is bound to the new printer.
4376 ****************************************************************************/
4377
4378 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4379 {
4380         bool result = False;
4381
4382         switch (level) {
4383                 case 2:
4384                         result = set_driver_init_2(printer->info_2);
4385                         break;
4386
4387                 default:
4388                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4389                                 level));
4390                         break;
4391         }
4392
4393         return result;
4394 }
4395
4396 /****************************************************************************
4397  Delete driver init data stored for a specified driver
4398 ****************************************************************************/
4399
4400 bool del_driver_init(const char *drivername)
4401 {
4402         char *key;
4403         bool ret;
4404
4405         if (!drivername || !*drivername) {
4406                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4407                 return false;
4408         }
4409
4410         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4411                 return false;
4412         }
4413
4414         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4415                                 drivername));
4416
4417         ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4418         SAFE_FREE(key);
4419         return ret;
4420 }
4421
4422 /****************************************************************************
4423  Pack up the DEVMODE and values for a printer into a 'driver init' entry
4424  in the tdb. Note: this is different from the driver entry and the printer
4425  entry. There should be a single driver init entry for each driver regardless
4426  of whether it was installed from NT or 2K. Technically, they should be
4427  different, but they work out to the same struct.
4428 ****************************************************************************/
4429
4430 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4431 {
4432         char *key = NULL;
4433         uint8 *buf;
4434         int buflen, len, ret;
4435         int retlen;
4436         TDB_DATA dbuf;
4437
4438         buf = NULL;
4439         buflen = 0;
4440
4441  again:
4442         len = 0;
4443         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4444
4445         retlen = pack_values( info->data, buf+len, buflen-len );
4446         if (retlen == -1) {
4447                 ret = -1;
4448                 goto done;
4449         }
4450         len += retlen;
4451
4452         if (buflen < len) {
4453                 buf = (uint8 *)SMB_REALLOC(buf, len);
4454                 if (!buf) {
4455                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4456                         ret = -1;
4457                         goto done;
4458                 }
4459                 buflen = len;
4460                 goto again;
4461         }
4462
4463         SAFE_FREE(key);
4464         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4465                 ret = (uint32)-1;
4466                 goto done;
4467         }
4468
4469         dbuf.dptr = buf;
4470         dbuf.dsize = len;
4471
4472         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4473
4474 done:
4475         if (ret == -1)
4476                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4477
4478         SAFE_FREE(buf);
4479
4480         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4481                  info->sharename, info->drivername));
4482
4483         return ret;
4484 }
4485
4486 /****************************************************************************
4487  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4488 ****************************************************************************/
4489
4490 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4491 {
4492         uint32 result;
4493
4494         dump_a_printer(printer, level);
4495
4496         switch (level) {
4497                 case 2:
4498                         result = update_driver_init_2(printer->info_2);
4499                         break;
4500                 default:
4501                         result = 1;
4502                         break;
4503         }
4504
4505         return result;
4506 }
4507
4508 /****************************************************************************
4509  Convert the printer data value, a REG_BINARY array, into an initialization
4510  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4511  got to keep the endians happy :).
4512 ****************************************************************************/
4513
4514 static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
4515                                 const uint8_t *data, uint32_t data_len)
4516 {
4517         struct spoolss_DeviceMode devmode;
4518         enum ndr_err_code ndr_err;
4519         DATA_BLOB blob;
4520
4521         ZERO_STRUCT(devmode);
4522
4523         blob = data_blob_const(data, data_len);
4524
4525         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
4526                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4527         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4528                 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4529                 return false;
4530         }
4531
4532         return convert_devicemode("", &devmode, &nt_devmode);
4533 }
4534
4535 /****************************************************************************
4536  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4537
4538  1. Use the driver's config DLL to this UNC printername and:
4539     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4540     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4541  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4542
4543  The last step triggers saving the "driver initialization" information for
4544  this printer into the tdb. Later, new printers that use this driver will
4545  have this initialization information bound to them. This simulates the
4546  driver initialization, as if it had run on the Samba server (as it would
4547  have done on NT).
4548
4549  The Win32 client side code requirement sucks! But until we can run arbitrary
4550  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4551
4552  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4553  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4554  about it and you will realize why.  JRR 010720
4555 ****************************************************************************/
4556
4557 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4558 {
4559         WERROR        status       = WERR_OK;
4560         TALLOC_CTX    *ctx         = NULL;
4561         NT_DEVICEMODE *nt_devmode  = NULL;
4562         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4563
4564         /*
4565          * When the DEVMODE is already set on the printer, don't try to unpack it.
4566          */
4567         DEBUG(8,("save_driver_init_2: Enter...\n"));
4568
4569         if ( !printer->info_2->devmode && data_len ) {
4570                 /*
4571                  * Set devmode on printer info, so entire printer initialization can be
4572                  * saved to tdb.
4573                  */
4574
4575                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4576                         return WERR_NOMEM;
4577
4578                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4579                         status = WERR_NOMEM;
4580                         goto done;
4581                 }
4582
4583                 ZERO_STRUCTP(nt_devmode);
4584
4585                 /*
4586                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4587                  * Convert it to to a devmode structure
4588                  */
4589                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4590                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4591                         status = WERR_INVALID_PARAM;
4592                         goto done;
4593                 }
4594
4595                 printer->info_2->devmode = nt_devmode;
4596         }
4597
4598         /*
4599          * Pack up and add (or update) the DEVMODE and any current printer data to
4600          * a 'driver init' element in the tdb
4601          *
4602          */
4603
4604         if ( update_driver_init(printer, 2) != 0 ) {
4605                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4606                 status = WERR_NOMEM;
4607                 goto done;
4608         }
4609
4610         /*
4611          * If driver initialization info was successfully saved, set the current
4612          * printer to match it. This allows initialization of the current printer
4613          * as well as the driver.
4614          */
4615         status = mod_a_printer(printer, 2);
4616         if (!W_ERROR_IS_OK(status)) {
4617                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4618                                   printer->info_2->printername));
4619         }
4620
4621   done:
4622         talloc_destroy(ctx);
4623         free_nt_devicemode( &nt_devmode );
4624
4625         printer->info_2->devmode = tmp_devmode;
4626
4627         return status;
4628 }
4629
4630 /****************************************************************************
4631  Update the driver init info (DEVMODE and specifics) for a printer
4632 ****************************************************************************/
4633
4634 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4635 {
4636         WERROR status = WERR_OK;
4637
4638         switch (level) {
4639                 case 2:
4640                         status = save_driver_init_2( printer, data, data_len );
4641                         break;
4642                 default:
4643                         status = WERR_UNKNOWN_LEVEL;
4644                         break;
4645         }
4646
4647         return status;
4648 }
4649
4650 /****************************************************************************
4651  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4652
4653  Previously the code had a memory allocation problem because it always
4654  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4655  as a long as the original handle is open.  So if the client made a lot
4656  of getprinter[data]() calls, the memory usage would climb.  Now we use
4657  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4658  still use the Printer_entry->ctx for maintaining the cache copy though
4659  since that object must live as long as the handle by definition.
4660                                                     --jerry
4661
4662 ****************************************************************************/
4663
4664 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4665                         const char *sharename, bool get_loc_com)
4666 {
4667         WERROR result;
4668         fstring servername;
4669
4670         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4671
4672         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4673                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4674                 return WERR_NOMEM;
4675         }
4676
4677         switch (level) {
4678                 case 2:
4679                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4680                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4681                                 TALLOC_FREE( *pp_printer );
4682                                 return WERR_NOMEM;
4683                         }
4684
4685                         if ( print_hnd )
4686                                 fstrcpy( servername, print_hnd->servername );
4687                         else {
4688                                 fstrcpy( servername, "%L" );
4689                                 standard_sub_basic( "", "", servername,
4690                                                     sizeof(servername)-1 );
4691                         }
4692
4693                         result = get_a_printer_2( (*pp_printer)->info_2,
4694                                         servername, sharename, get_loc_com);
4695
4696                         /* we have a new printer now.  Save it with this handle */
4697
4698                         if ( !W_ERROR_IS_OK(result) ) {
4699                                 TALLOC_FREE( *pp_printer );
4700                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4701                                         sharename, (unsigned int)level, win_errstr(result)));
4702                                 return result;
4703                         }
4704
4705                         dump_a_printer( *pp_printer, level);
4706
4707                         break;
4708
4709                 default:
4710                         TALLOC_FREE( *pp_printer );
4711                         return WERR_UNKNOWN_LEVEL;
4712         }
4713
4714         return WERR_OK;
4715 }
4716
4717 WERROR get_a_printer( Printer_entry *print_hnd,
4718                         NT_PRINTER_INFO_LEVEL **pp_printer,
4719                         uint32 level,
4720                         const char *sharename)
4721 {
4722         return get_a_printer_internal(print_hnd, pp_printer, level,
4723                                         sharename, true);
4724 }
4725
4726 WERROR get_a_printer_search( Printer_entry *print_hnd,
4727                         NT_PRINTER_INFO_LEVEL **pp_printer,
4728                         uint32 level,
4729                         const char *sharename)
4730 {
4731         return get_a_printer_internal(print_hnd, pp_printer, level,
4732                                         sharename, false);
4733 }
4734
4735 /****************************************************************************
4736  Deletes a NT_PRINTER_INFO_LEVEL struct.
4737 ****************************************************************************/
4738
4739 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4740 {
4741         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4742
4743         if ( !printer )
4744                 return 0;
4745
4746         switch (level) {
4747                 case 2:
4748                         if ( printer->info_2 )
4749                                 free_nt_printer_info_level_2(&printer->info_2);
4750                         break;
4751
4752                 default:
4753                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4754                         return 1;
4755         }
4756
4757         TALLOC_FREE(*pp_printer);
4758
4759         return 0;
4760 }
4761
4762 /****************************************************************************
4763 ****************************************************************************/
4764 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4765 {
4766         uint32 result;
4767         DEBUG(104,("adding a printer at level [%d]\n", level));
4768         dump_a_printer_driver(driver, level);
4769
4770         switch (level) {
4771                 case 3:
4772                         result=add_a_printer_driver_3(driver.info_3);
4773                         break;
4774
4775                 case 6:
4776                         result=add_a_printer_driver_6(driver.info_6);
4777                         break;
4778
4779                 default:
4780                         result=1;
4781                         break;
4782         }
4783
4784         return result;
4785 }
4786 /****************************************************************************
4787 ****************************************************************************/
4788
4789 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
4790                             const char *drivername, const char *architecture,
4791                             uint32_t version)
4792 {
4793         WERROR result;
4794
4795         switch (level) {
4796                 case 3:
4797                         /* Sometime we just want any version of the driver */
4798
4799                         if ( version == DRIVER_ANY_VERSION ) {
4800                                 /* look for Win2k first and then for NT4 */
4801                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4802                                                 architecture, 3);
4803
4804                                 if ( !W_ERROR_IS_OK(result) ) {
4805                                         result = get_a_printer_driver_3( &driver->info_3,
4806                                                         drivername, architecture, 2 );
4807                                 }
4808                         } else {
4809                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4810                                         architecture, version);
4811                         }
4812                         break;
4813
4814                 default:
4815                         result=W_ERROR(1);
4816                         break;
4817         }
4818
4819         if (W_ERROR_IS_OK(result))
4820                 dump_a_printer_driver(*driver, level);
4821
4822         return result;
4823 }
4824
4825 /****************************************************************************
4826 ****************************************************************************/
4827 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4828 {
4829         uint32 result;
4830
4831         switch (level) {
4832                 case 3:
4833                 {
4834                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4835                         if (driver.info_3 != NULL)
4836                         {
4837                                 info3=driver.info_3;
4838                                 SAFE_FREE(info3->dependentfiles);
4839                                 ZERO_STRUCTP(info3);
4840                                 SAFE_FREE(info3);
4841                                 result=0;
4842                         } else {
4843                                 result=4;
4844                         }
4845                         break;
4846                 }
4847                 case 6:
4848                 {
4849                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4850                         if (driver.info_6 != NULL) {
4851                                 info6=driver.info_6;
4852                                 SAFE_FREE(info6->dependentfiles);
4853                                 SAFE_FREE(info6->previousnames);
4854                                 ZERO_STRUCTP(info6);
4855                                 SAFE_FREE(info6);
4856                                 result=0;
4857                         } else {
4858                                 result=4;
4859                         }
4860                         break;
4861                 }
4862                 default:
4863                         result=1;
4864                         break;
4865         }
4866         return result;
4867 }
4868
4869
4870 /****************************************************************************
4871   Determine whether or not a particular driver is currently assigned
4872   to a printer
4873 ****************************************************************************/
4874
4875 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4876 {
4877         int snum;
4878         int n_services = lp_numservices();
4879         NT_PRINTER_INFO_LEVEL *printer = NULL;
4880         bool in_use = False;
4881
4882         if ( !info_3 )
4883                 return False;
4884
4885         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4886
4887         /* loop through the printers.tdb and check for the drivername */
4888
4889         for (snum=0; snum<n_services && !in_use; snum++) {
4890                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4891                         continue;
4892
4893                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4894                         continue;
4895
4896                 if ( strequal(info_3->name, printer->info_2->drivername) )
4897                         in_use = True;
4898
4899                 free_a_printer( &printer, 2 );
4900         }
4901
4902         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4903
4904         if ( in_use ) {
4905                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4906                 WERROR werr;
4907
4908                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4909
4910                 /* we can still remove the driver if there is one of
4911                    "Windows NT x86" version 2 or 3 left */
4912
4913                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4914                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4915                 }
4916                 else {
4917                         switch ( info_3->cversion ) {
4918                         case 2:
4919                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4920                                 break;
4921                         case 3:
4922                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4923                                 break;
4924                         default:
4925                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4926                                         info_3->cversion));
4927                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4928                                 break;
4929                         }
4930                 }
4931
4932                 /* now check the error code */
4933
4934                 if ( W_ERROR_IS_OK(werr) ) {
4935                         /* it's ok to remove the driver, we have other architctures left */
4936                         in_use = False;
4937                         free_a_printer_driver( d, 3 );
4938                 }
4939         }
4940
4941         /* report that the driver is not in use by default */
4942
4943         return in_use;
4944 }
4945
4946
4947 /**********************************************************************
4948  Check to see if a ogiven file is in use by *info
4949  *********************************************************************/
4950
4951 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4952 {
4953         int i = 0;
4954
4955         if ( !info )
4956                 return False;
4957
4958         /* mz: skip files that are in the list but already deleted */
4959         if (!file || !file[0]) {
4960                 return false;
4961         }
4962
4963         if ( strequal(file, info->driverpath) )
4964                 return True;
4965
4966         if ( strequal(file, info->datafile) )
4967                 return True;
4968
4969         if ( strequal(file, info->configfile) )
4970                 return True;
4971
4972         if ( strequal(file, info->helpfile) )
4973                 return True;
4974
4975         /* see of there are any dependent files to examine */
4976
4977         if ( !info->dependentfiles )
4978                 return False;
4979
4980         while ( *info->dependentfiles[i] ) {
4981                 if ( strequal(file, info->dependentfiles[i]) )
4982                         return True;
4983                 i++;
4984         }
4985
4986         return False;
4987
4988 }
4989
4990 /**********************************************************************
4991  Utility function to remove the dependent file pointed to by the
4992  input parameter from the list
4993  *********************************************************************/
4994
4995 static void trim_dependent_file( fstring files[], int idx )
4996 {
4997
4998         /* bump everything down a slot */
4999
5000         while( *files[idx+1] ) {
5001                 fstrcpy( files[idx], files[idx+1] );
5002                 idx++;
5003         }
5004
5005         *files[idx] = '\0';
5006
5007         return;
5008 }
5009
5010 /**********************************************************************
5011  Check if any of the files used by src are also used by drv
5012  *********************************************************************/
5013
5014 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
5015                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
5016 {
5017         bool    in_use = False;
5018         int     i = 0;
5019
5020         if ( !src || !drv )
5021                 return False;
5022
5023         /* check each file.  Remove it from the src structure if it overlaps */
5024
5025         if ( drv_file_in_use(src->driverpath, drv) ) {
5026                 in_use = True;
5027                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
5028                 fstrcpy( src->driverpath, "" );
5029         }
5030
5031         if ( drv_file_in_use(src->datafile, drv) ) {
5032                 in_use = True;
5033                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
5034                 fstrcpy( src->datafile, "" );
5035         }
5036
5037         if ( drv_file_in_use(src->configfile, drv) ) {
5038                 in_use = True;
5039                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5040                 fstrcpy( src->configfile, "" );
5041         }
5042
5043         if ( drv_file_in_use(src->helpfile, drv) ) {
5044                 in_use = True;
5045                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5046                 fstrcpy( src->helpfile, "" );
5047         }
5048
5049         /* are there any dependentfiles to examine? */
5050
5051         if ( !src->dependentfiles )
5052                 return in_use;
5053
5054         while ( *src->dependentfiles[i] ) {
5055                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5056                         in_use = True;
5057                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5058                         trim_dependent_file( src->dependentfiles, i );
5059                 } else
5060                         i++;
5061         }
5062
5063         return in_use;
5064 }
5065
5066 /****************************************************************************
5067   Determine whether or not a particular driver files are currently being
5068   used by any other driver.
5069
5070   Return value is True if any files were in use by other drivers
5071   and False otherwise.
5072
5073   Upon return, *info has been modified to only contain the driver files
5074   which are not in use
5075
5076   Fix from mz:
5077
5078   This needs to check all drivers to ensure that all files in use
5079   have been removed from *info, not just the ones in the first
5080   match.
5081 ****************************************************************************/
5082
5083 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5084 {
5085         int                             i;
5086         int                             ndrivers;
5087         uint32                          version;
5088         fstring                         *list = NULL;
5089         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5090         bool in_use = false;
5091
5092         if ( !info )
5093                 return False;
5094
5095         version = info->cversion;
5096
5097         /* loop over all driver versions */
5098
5099         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5100
5101         /* get the list of drivers */
5102
5103         list = NULL;
5104         ndrivers = get_ntdrivers(&list, info->environment, version);
5105
5106         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5107                 ndrivers, info->environment, version));
5108
5109         /* check each driver for overlap in files */
5110
5111         for (i=0; i<ndrivers; i++) {
5112                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5113
5114                 ZERO_STRUCT(driver);
5115
5116                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5117                         SAFE_FREE(list);
5118                         return True;
5119                 }
5120
5121                 /* check if d2 uses any files from d1 */
5122                 /* only if this is a different driver than the one being deleted */
5123
5124                 if ( !strequal(info->name, driver.info_3->name) ) {
5125                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
5126                                 /* mz: Do not instantly return -
5127                                  * we need to ensure this file isn't
5128                                  * also in use by other drivers. */
5129                                 in_use = true;
5130                         }
5131                 }
5132
5133                 free_a_printer_driver(driver, 3);
5134         }
5135
5136         SAFE_FREE(list);
5137
5138         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5139
5140         driver.info_3 = info;
5141
5142         if ( DEBUGLEVEL >= 20 )
5143                 dump_a_printer_driver( driver, 3 );
5144
5145         return in_use;
5146 }
5147
5148 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5149                                         const char *name)
5150 {
5151         struct smb_filename *smb_fname = NULL;
5152         NTSTATUS status;
5153
5154         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5155             &smb_fname);
5156         if (!NT_STATUS_IS_OK(status)) {
5157                 return status;
5158         }
5159
5160         status = unlink_internals(conn, NULL, 0, smb_fname, false);
5161
5162         TALLOC_FREE(smb_fname);
5163         return status;
5164 }
5165
5166 /****************************************************************************
5167   Actually delete the driver files.  Make sure that
5168   printer_driver_files_in_use() return False before calling
5169   this.
5170 ****************************************************************************/
5171
5172 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5173                                 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
5174 {
5175         int i = 0;
5176         char *s;
5177         const char *file;
5178         connection_struct *conn;
5179         NTSTATUS nt_status;
5180         char *oldcwd;
5181         fstring printdollar;
5182         int printdollar_snum;
5183         bool ret = false;
5184
5185         if ( !info_3 )
5186                 return False;
5187
5188         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5189
5190         fstrcpy(printdollar, "print$");
5191
5192         printdollar_snum = find_service(printdollar);
5193         if (printdollar_snum == -1) {
5194                 return false;
5195         }
5196
5197         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5198                                        lp_pathname(printdollar_snum),
5199                                        rpc_pipe->server_info, &oldcwd);
5200         if (!NT_STATUS_IS_OK(nt_status)) {
5201                 DEBUG(0,("delete_driver_files: create_conn_struct "
5202                          "returned %s\n", nt_errstr(nt_status)));
5203                 return false;
5204         }
5205
5206         if ( !CAN_WRITE(conn) ) {
5207                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5208                 goto fail;
5209         }
5210
5211         /* now delete the files; must strip the '\print$' string from
5212            fron of path                                                */
5213
5214         if ( *info_3->driverpath ) {
5215                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5216                         file = s;
5217                         DEBUG(10,("deleting driverfile [%s]\n", s));
5218                         driver_unlink_internals(conn, file);
5219                 }
5220         }
5221
5222         if ( *info_3->configfile ) {
5223                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5224                         file = s;
5225                         DEBUG(10,("deleting configfile [%s]\n", s));
5226                         driver_unlink_internals(conn, file);
5227                 }
5228         }
5229
5230         if ( *info_3->datafile ) {
5231                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5232                         file = s;
5233                         DEBUG(10,("deleting datafile [%s]\n", s));
5234                         driver_unlink_internals(conn, file);
5235                 }
5236         }
5237
5238         if ( *info_3->helpfile ) {
5239                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5240                         file = s;
5241                         DEBUG(10,("deleting helpfile [%s]\n", s));
5242                         driver_unlink_internals(conn, file);
5243                 }
5244         }
5245
5246         /* check if we are done removing files */
5247
5248         if ( info_3->dependentfiles ) {
5249                 while ( info_3->dependentfiles[i][0] ) {
5250                         char *p;
5251
5252                         /* bypass the "\print$" portion of the path */
5253
5254                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5255                                 file = p;
5256                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5257                                 driver_unlink_internals(conn, file);
5258                         }
5259
5260                         i++;
5261                 }
5262         }
5263
5264         goto done;
5265  fail:
5266         ret = false;
5267  done:
5268         if (conn != NULL) {
5269                 vfs_ChDir(conn, oldcwd);
5270                 conn_free(conn);
5271         }
5272         return ret;
5273 }
5274
5275 /****************************************************************************
5276  Remove a printer driver from the TDB.  This assumes that the the driver was
5277  previously looked up.
5278  ***************************************************************************/
5279
5280 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5281                              NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3,
5282                              uint32 version, bool delete_files )
5283 {
5284         char *key = NULL;
5285         const char     *arch;
5286         TDB_DATA        dbuf;
5287         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
5288
5289         /* delete the tdb data first */
5290
5291         arch = get_short_archi(info_3->environment);
5292         if (!arch) {
5293                 return WERR_UNKNOWN_PRINTER_DRIVER;
5294         }
5295         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5296                         arch, version, info_3->name) < 0) {
5297                 return WERR_NOMEM;
5298         }
5299
5300         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5301                 key, delete_files ? "TRUE" : "FALSE" ));
5302
5303         ctr.info_3 = info_3;
5304         dump_a_printer_driver( ctr, 3 );
5305
5306         /* check if the driver actually exists for this environment */
5307
5308         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5309         if ( !dbuf.dptr ) {
5310                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5311                 SAFE_FREE(key);
5312                 return WERR_UNKNOWN_PRINTER_DRIVER;
5313         }
5314
5315         SAFE_FREE( dbuf.dptr );
5316
5317         /* ok... the driver exists so the delete should return success */
5318
5319         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5320                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5321                 SAFE_FREE(key);
5322                 return WERR_ACCESS_DENIED;
5323         }
5324
5325         /*
5326          * now delete any associated files if delete_files == True
5327          * even if this part failes, we return succes because the
5328          * driver doesn not exist any more
5329          */
5330
5331         if ( delete_files )
5332                 delete_driver_files(rpc_pipe, info_3);
5333
5334         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5335         SAFE_FREE(key);
5336
5337         return WERR_OK;
5338 }
5339
5340 /****************************************************************************
5341  Store a security desc for a printer.
5342 ****************************************************************************/
5343
5344 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5345 {
5346         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5347         SEC_DESC_BUF *old_secdesc_ctr = NULL;
5348         TALLOC_CTX *mem_ctx = NULL;
5349         TDB_DATA kbuf;
5350         TDB_DATA dbuf;
5351         DATA_BLOB blob;
5352         WERROR status;
5353         NTSTATUS nt_status;
5354
5355         mem_ctx = talloc_init("nt_printing_setsec");
5356         if (mem_ctx == NULL)
5357                 return WERR_NOMEM;
5358
5359         /* The old owner and group sids of the security descriptor are not
5360            present when new ACEs are added or removed by changing printer
5361            permissions through NT.  If they are NULL in the new security
5362            descriptor then copy them over from the old one. */
5363
5364         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5365                 DOM_SID *owner_sid, *group_sid;
5366                 SEC_ACL *dacl, *sacl;
5367                 SEC_DESC *psd = NULL;
5368                 size_t size;
5369
5370                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5371                         status = WERR_NOMEM;
5372                         goto out;
5373                 }
5374
5375                 /* Pick out correct owner and group sids */
5376
5377                 owner_sid = secdesc_ctr->sd->owner_sid ?
5378                         secdesc_ctr->sd->owner_sid :
5379                         old_secdesc_ctr->sd->owner_sid;
5380
5381                 group_sid = secdesc_ctr->sd->group_sid ?
5382                         secdesc_ctr->sd->group_sid :
5383                         old_secdesc_ctr->sd->group_sid;
5384
5385                 dacl = secdesc_ctr->sd->dacl ?
5386                         secdesc_ctr->sd->dacl :
5387                         old_secdesc_ctr->sd->dacl;
5388
5389                 sacl = secdesc_ctr->sd->sacl ?
5390                         secdesc_ctr->sd->sacl :
5391                         old_secdesc_ctr->sd->sacl;
5392
5393                 /* Make a deep copy of the security descriptor */
5394
5395                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5396                                     owner_sid, group_sid,
5397                                     sacl,
5398                                     dacl,
5399                                     &size);
5400
5401                 if (!psd) {
5402                         status = WERR_NOMEM;
5403                         goto out;
5404                 }
5405
5406                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5407         }
5408
5409         if (!new_secdesc_ctr) {
5410                 new_secdesc_ctr = secdesc_ctr;
5411         }
5412
5413         /* Store the security descriptor in a tdb */
5414
5415         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5416                                           &blob.data, &blob.length);
5417         if (!NT_STATUS_IS_OK(nt_status)) {
5418                 status = ntstatus_to_werror(nt_status);
5419                 goto out;
5420         }
5421
5422         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5423
5424         dbuf.dptr = (unsigned char *)blob.data;
5425         dbuf.dsize = blob.length;
5426
5427         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5428                 status = WERR_OK;
5429         } else {
5430                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5431                 status = WERR_BADFUNC;
5432         }
5433
5434         /* Free malloc'ed memory */
5435         talloc_free(blob.data);
5436
5437  out:
5438
5439         if (mem_ctx)
5440                 talloc_destroy(mem_ctx);
5441         return status;
5442 }
5443
5444 /****************************************************************************
5445  Construct a default security descriptor buffer for a printer.
5446 ****************************************************************************/
5447
5448 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5449 {
5450         SEC_ACE ace[5]; /* max number of ace entries */
5451         int i = 0;
5452         uint32_t sa;
5453         SEC_ACL *psa = NULL;
5454         SEC_DESC_BUF *sdb = NULL;
5455         SEC_DESC *psd = NULL;
5456         DOM_SID adm_sid;
5457         size_t sd_size;
5458
5459         /* Create an ACE where Everyone is allowed to print */
5460
5461         sa = PRINTER_ACE_PRINT;
5462         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5463                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5464
5465         /* Add the domain admins group if we are a DC */
5466
5467         if ( IS_DC ) {
5468                 DOM_SID domadmins_sid;
5469
5470                 sid_copy(&domadmins_sid, get_global_sam_sid());
5471                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5472
5473                 sa = PRINTER_ACE_FULL_CONTROL;
5474                 init_sec_ace(&ace[i++], &domadmins_sid,
5475                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5476                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5477                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5478                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5479         }
5480         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5481                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5482
5483                 sa = PRINTER_ACE_FULL_CONTROL;
5484                 init_sec_ace(&ace[i++], &adm_sid,
5485                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5486                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5487                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5488                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5489         }
5490
5491         /* add BUILTIN\Administrators as FULL CONTROL */
5492
5493         sa = PRINTER_ACE_FULL_CONTROL;
5494         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5495                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5496                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5497         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5498                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5499                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5500
5501         /* Make the security descriptor owned by the BUILTIN\Administrators */
5502
5503         /* The ACL revision number in rpc_secdesc.h differs from the one
5504            created by NT when setting ACE entries in printer
5505            descriptors.  NT4 complains about the property being edited by a
5506            NT5 machine. */
5507
5508         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5509                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5510                         &global_sid_Builtin_Administrators,
5511                         &global_sid_Builtin_Administrators,
5512                         NULL, psa, &sd_size);
5513         }
5514
5515         if (!psd) {
5516                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5517                 return NULL;
5518         }
5519
5520         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5521
5522         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5523                  (unsigned int)sd_size));
5524
5525         return sdb;
5526 }
5527
5528 /****************************************************************************
5529  Get a security desc for a printer.
5530 ****************************************************************************/
5531
5532 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5533 {
5534         TDB_DATA kbuf;
5535         TDB_DATA dbuf;
5536         DATA_BLOB blob;
5537         char *temp;
5538         NTSTATUS status;
5539
5540         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5541                 sharename = temp + 1;
5542         }
5543
5544         /* Fetch security descriptor from tdb */
5545
5546         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5547
5548         dbuf = tdb_fetch(tdb_printers, kbuf);
5549         if (dbuf.dptr) {
5550
5551                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5552                                                  secdesc_ctr);
5553                 SAFE_FREE(dbuf.dptr);
5554
5555                 if (NT_STATUS_IS_OK(status)) {
5556                         return true;
5557                 }
5558         }
5559
5560         *secdesc_ctr = construct_default_printer_sdb(ctx);
5561         if (!*secdesc_ctr) {
5562                 return false;
5563         }
5564
5565         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5566                                        &blob.data, &blob.length);
5567         if (NT_STATUS_IS_OK(status)) {
5568                 dbuf.dptr = (unsigned char *)blob.data;
5569                 dbuf.dsize = blob.length;
5570                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5571                 talloc_free(blob.data);
5572         }
5573
5574         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5575            this security descriptor has been created when winbindd was
5576            down.  Take ownership of security descriptor. */
5577
5578         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5579                 DOM_SID owner_sid;
5580
5581                 /* Change sd owner to workgroup administrator */
5582
5583                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5584                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5585                         SEC_DESC *psd = NULL;
5586                         size_t size;
5587
5588                         /* Create new sd */
5589
5590                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5591
5592                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5593                                             &owner_sid,
5594                                             (*secdesc_ctr)->sd->group_sid,
5595                                             (*secdesc_ctr)->sd->sacl,
5596                                             (*secdesc_ctr)->sd->dacl,
5597                                             &size);
5598
5599                         if (!psd) {
5600                                 return False;
5601                         }
5602
5603                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5604                         if (!new_secdesc_ctr) {
5605                                 return False;
5606                         }
5607
5608                         /* Swap with other one */
5609
5610                         *secdesc_ctr = new_secdesc_ctr;
5611
5612                         /* Set it */
5613
5614                         nt_printing_setsec(sharename, *secdesc_ctr);
5615                 }
5616         }
5617
5618         if (DEBUGLEVEL >= 10) {
5619                 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5620                 int i;
5621
5622                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5623                            sharename, the_acl->num_aces));
5624
5625                 for (i = 0; i < the_acl->num_aces; i++) {
5626                         DEBUG(10, ("%s %d %d 0x%08x\n",
5627                                    sid_string_dbg(&the_acl->aces[i].trustee),
5628                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5629                                    the_acl->aces[i].access_mask));
5630                 }
5631         }
5632
5633         return True;
5634 }
5635
5636 /* error code:
5637         0: everything OK
5638         1: level not implemented
5639         2: file doesn't exist
5640         3: can't allocate memory
5641         4: can't free memory
5642         5: non existant struct
5643 */
5644
5645 /*
5646         A printer and a printer driver are 2 different things.
5647         NT manages them separatelly, Samba does the same.
5648         Why ? Simply because it's easier and it makes sense !
5649
5650         Now explanation: You have 3 printers behind your samba server,
5651         2 of them are the same make and model (laser A and B). But laser B
5652         has an 3000 sheet feeder and laser A doesn't such an option.
5653         Your third printer is an old dot-matrix model for the accounting :-).
5654
5655         If the /usr/local/samba/lib directory (default dir), you will have
5656         5 files to describe all of this.
5657
5658         3 files for the printers (1 by printer):
5659                 NTprinter_laser A
5660                 NTprinter_laser B
5661                 NTprinter_accounting
5662         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5663                 NTdriver_printer model X
5664                 NTdriver_printer model Y
5665
5666 jfm: I should use this comment for the text file to explain
5667         same thing for the forms BTW.
5668         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5669
5670 */
5671
5672 /* Convert generic access rights to printer object specific access rights.
5673    It turns out that NT4 security descriptors use generic access rights and
5674    NT5 the object specific ones. */
5675
5676 void map_printer_permissions(SEC_DESC *sd)
5677 {
5678         int i;
5679
5680         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5681                 se_map_generic(&sd->dacl->aces[i].access_mask,
5682                                &printer_generic_mapping);
5683         }
5684 }
5685
5686 void map_job_permissions(SEC_DESC *sd)
5687 {
5688         int i;
5689
5690         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5691                 se_map_generic(&sd->dacl->aces[i].access_mask,
5692                                &job_generic_mapping);
5693         }
5694 }
5695
5696
5697 /****************************************************************************
5698  Check a user has permissions to perform the given operation.  We use the
5699  permission constants defined in include/rpc_spoolss.h to check the various
5700  actions we perform when checking printer access.
5701
5702    PRINTER_ACCESS_ADMINISTER:
5703        print_queue_pause, print_queue_resume, update_printer_sec,
5704        update_printer, spoolss_addprinterex_level_2,
5705        _spoolss_setprinterdata
5706
5707    PRINTER_ACCESS_USE:
5708        print_job_start
5709
5710    JOB_ACCESS_ADMINISTER:
5711        print_job_delete, print_job_pause, print_job_resume,
5712        print_queue_purge
5713
5714   Try access control in the following order (for performance reasons):
5715     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
5716     2)  check security descriptor (bit comparisons in memory)
5717     3)  "printer admins" (may result in numerous calls to winbind)
5718
5719  ****************************************************************************/
5720 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5721                         int access_type)
5722 {
5723         SEC_DESC_BUF *secdesc = NULL;
5724         uint32 access_granted;
5725         NTSTATUS status;
5726         const char *pname;
5727         TALLOC_CTX *mem_ctx = NULL;
5728         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5729
5730         /* If user is NULL then use the current_user structure */
5731
5732         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5733
5734         if (server_info->utok.uid == sec_initial_uid()
5735             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5736                 return True;
5737         }
5738
5739         /* Get printer name */
5740
5741         pname = PRINTERNAME(snum);
5742
5743         if (!pname || !*pname) {
5744                 errno = EACCES;
5745                 return False;
5746         }
5747
5748         /* Get printer security descriptor */
5749
5750         if(!(mem_ctx = talloc_init("print_access_check"))) {
5751                 errno = ENOMEM;
5752                 return False;
5753         }
5754
5755         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5756                 talloc_destroy(mem_ctx);
5757                 errno = ENOMEM;
5758                 return False;
5759         }
5760
5761         if (access_type == JOB_ACCESS_ADMINISTER) {
5762                 SEC_DESC_BUF *parent_secdesc = secdesc;
5763
5764                 /* Create a child security descriptor to check permissions
5765                    against.  This is because print jobs are child objects
5766                    objects of a printer. */
5767
5768                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5769
5770                 if (!NT_STATUS_IS_OK(status)) {
5771                         talloc_destroy(mem_ctx);
5772                         errno = map_errno_from_nt_status(status);
5773                         return False;
5774                 }
5775
5776                 map_job_permissions(secdesc->sd);
5777         } else {
5778                 map_printer_permissions(secdesc->sd);
5779         }
5780
5781         /* Check access */
5782         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5783                                  &access_granted);
5784
5785         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5786
5787         /* see if we need to try the printer admin list */
5788
5789         if ((access_granted == 0) &&
5790             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5791                                          NULL, NULL, server_info->ptok,
5792                                          lp_printer_admin(snum)))) {
5793                 talloc_destroy(mem_ctx);
5794                 return True;
5795         }
5796
5797         talloc_destroy(mem_ctx);
5798
5799         if (!NT_STATUS_IS_OK(status)) {
5800                 errno = EACCES;
5801         }
5802
5803         return NT_STATUS_IS_OK(status);
5804 }
5805
5806 /****************************************************************************
5807  Check the time parameters allow a print operation.
5808 *****************************************************************************/
5809
5810 bool print_time_access_check(const char *servicename)
5811 {
5812         NT_PRINTER_INFO_LEVEL *printer = NULL;
5813         bool ok = False;
5814         time_t now = time(NULL);
5815         struct tm *t;
5816         uint32 mins;
5817
5818         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5819                 return False;
5820
5821         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5822                 ok = True;
5823
5824         t = gmtime(&now);
5825         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5826
5827         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5828                 ok = True;
5829
5830         free_a_printer(&printer, 2);
5831
5832         if (!ok)
5833                 errno = EACCES;
5834
5835         return ok;
5836 }
5837
5838 /****************************************************************************
5839  Fill in the servername sent in the _spoolss_open_printer_ex() call
5840 ****************************************************************************/
5841
5842 char* get_server_name( Printer_entry *printer )
5843 {
5844         return printer->servername;
5845 }
5846
5847