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