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