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