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