We may use 127k read/write for encrypted connections.
[ira/wip.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23
24 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, fsp->fh->fd, 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, fsp->fh->fd,
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, fsp->fh->fd, 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, fsp->fh->fd, 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, fsp->fh->fd, &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, fsp->fh->fd, &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, 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                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3320
3321         if (!ADS_ERR_OK(ads_rc))
3322                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3323         
3324         talloc_destroy(ctx);
3325
3326         /* retreive the guid and store it locally */
3327         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3328                 ZERO_STRUCT(guid);
3329                 ads_pull_guid(ads, res, &guid);
3330                 ads_msgfree(ads, res);
3331                 store_printer_guid(printer->info_2, guid);
3332                 win_rc = mod_a_printer(printer, 2);
3333         } 
3334
3335         SAFE_FREE(prt_dn);
3336         return win_rc;
3337 }
3338
3339 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3340                                        NT_PRINTER_INFO_LEVEL *printer)
3341 {
3342         ADS_STATUS ads_rc;
3343         LDAPMessage *res;
3344         char *prt_dn = NULL;
3345
3346         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3347
3348         /* remove the printer from the directory */
3349         ads_rc = ads_find_printer_on_server(ads, &res, 
3350                             printer->info_2->sharename, global_myname());
3351
3352         if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3353                 prt_dn = ads_get_dn(ads, res);
3354                 if (!prt_dn) {
3355                         ads_msgfree(ads, res);
3356                         return WERR_NOMEM;
3357                 }
3358                 ads_rc = ads_del_dn(ads, prt_dn);
3359                 ads_memfree(ads, prt_dn);
3360         }
3361
3362         ads_msgfree(ads, res);
3363         return WERR_OK;
3364 }
3365
3366 /****************************************************************************
3367  * Publish a printer in the directory
3368  *
3369  * @param snum describing printer service
3370  * @return WERROR indicating status of publishing
3371  ***************************************************************************/
3372
3373 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3374 {
3375         ADS_STATUS ads_rc;
3376         ADS_STRUCT *ads = NULL;
3377         NT_PRINTER_INFO_LEVEL *printer = NULL;
3378         WERROR win_rc;
3379
3380         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3381         if (!W_ERROR_IS_OK(win_rc))
3382                 goto done;
3383
3384         switch (action) {
3385         case SPOOL_DS_PUBLISH:
3386         case SPOOL_DS_UPDATE:
3387                 /* set the DsSpooler info and attributes */
3388                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3389                         win_rc = WERR_NOMEM;
3390                         goto done;
3391                 }
3392
3393                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3394                 break;
3395         case SPOOL_DS_UNPUBLISH:
3396                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3397                 break;
3398         default:
3399                 win_rc = WERR_NOT_SUPPORTED;
3400                 goto done;
3401         }
3402
3403         win_rc = mod_a_printer(printer, 2);
3404         if (!W_ERROR_IS_OK(win_rc)) {
3405                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3406                 goto done;
3407         }
3408
3409         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3410         if (!ads) {
3411                 DEBUG(3, ("ads_init() failed\n"));
3412                 win_rc = WERR_SERVER_UNAVAILABLE;
3413                 goto done;
3414         }
3415         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3416         SAFE_FREE(ads->auth.password);
3417         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3418                 NULL, NULL);
3419
3420         /* ads_connect() will find the DC for us */                                         
3421         ads_rc = ads_connect(ads);
3422         if (!ADS_ERR_OK(ads_rc)) {
3423                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3424                 win_rc = WERR_ACCESS_DENIED;
3425                 goto done;
3426         }
3427
3428         switch (action) {
3429         case SPOOL_DS_PUBLISH:
3430         case SPOOL_DS_UPDATE:
3431                 win_rc = nt_printer_publish_ads(ads, printer);
3432                 break;
3433         case SPOOL_DS_UNPUBLISH:
3434                 win_rc = nt_printer_unpublish_ads(ads, printer);
3435                 break;
3436         }
3437
3438 done:
3439         free_a_printer(&printer, 2);
3440         ads_destroy(&ads);
3441         return win_rc;
3442 }
3443
3444 WERROR check_published_printers(void)
3445 {
3446         ADS_STATUS ads_rc;
3447         ADS_STRUCT *ads = NULL;
3448         int snum;
3449         int n_services = lp_numservices();
3450         NT_PRINTER_INFO_LEVEL *printer = NULL;
3451
3452         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3453         if (!ads) {
3454                 DEBUG(3, ("ads_init() failed\n"));
3455                 return WERR_SERVER_UNAVAILABLE;
3456         }
3457         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3458         SAFE_FREE(ads->auth.password);
3459         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3460                 NULL, NULL);
3461
3462         /* ads_connect() will find the DC for us */                                         
3463         ads_rc = ads_connect(ads);
3464         if (!ADS_ERR_OK(ads_rc)) {
3465                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3466                 ads_destroy(&ads);
3467                 ads_kdestroy("MEMORY:prtpub_cache");
3468                 return WERR_ACCESS_DENIED;
3469         }
3470
3471         for (snum = 0; snum < n_services; snum++) {
3472                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3473                         continue;
3474
3475                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3476                                                 lp_servicename(snum))) &&
3477                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3478                         nt_printer_publish_ads(ads, printer);
3479
3480                 free_a_printer(&printer, 2);
3481         }
3482
3483         ads_destroy(&ads);
3484         ads_kdestroy("MEMORY:prtpub_cache");
3485         return WERR_OK;
3486 }
3487
3488 bool is_printer_published(Printer_entry *print_hnd, int snum, 
3489                           struct GUID *guid)
3490 {
3491         NT_PRINTER_INFO_LEVEL *printer = NULL;
3492         REGVAL_CTR *ctr;
3493         REGISTRY_VALUE *guid_val;
3494         WERROR win_rc;
3495         int i;
3496         bool ret = False;
3497
3498         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3499
3500         if (!W_ERROR_IS_OK(win_rc) ||
3501             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3502             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3503             !(ctr = printer->info_2->data->keys[i].values) ||
3504             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) 
3505         {
3506                 free_a_printer(&printer, 2);
3507                 return False;
3508         }
3509
3510         /* fetching printer guids really ought to be a separate function. */
3511
3512         if ( guid ) {   
3513                 fstring guid_str;
3514                 
3515                 /* We used to store the guid as REG_BINARY, then swapped 
3516                    to REG_SZ for Vista compatibility so check for both */
3517
3518                 switch ( regval_type(guid_val) ){
3519                 case REG_SZ:            
3520                         rpcstr_pull( guid_str, regval_data_p(guid_val), 
3521                                      sizeof(guid_str)-1, -1, STR_TERMINATE );
3522                         ret = smb_string_to_uuid( guid_str, guid );
3523                         break;                  
3524                 case REG_BINARY:
3525                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3526                                 ret = False;
3527                                 break;
3528                         }
3529                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3530                         break;
3531                 default:
3532                         DEBUG(0,("is_printer_published: GUID value stored as "
3533                                  "invaluid type (%d)\n", regval_type(guid_val) ));                      
3534                         break;
3535                 }
3536         }
3537
3538         free_a_printer(&printer, 2);
3539         return ret;
3540 }
3541 #else
3542 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3543 {
3544         return WERR_OK;
3545 }
3546
3547 WERROR check_published_printers(void)
3548 {
3549         return WERR_OK;
3550 }
3551
3552 bool is_printer_published(Printer_entry *print_hnd, int snum, 
3553                           struct GUID *guid)
3554 {
3555         return False;
3556 }
3557 #endif /* HAVE_ADS */
3558
3559 /****************************************************************************
3560  ***************************************************************************/
3561  
3562 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3563 {
3564         NT_PRINTER_DATA *data;
3565         int             i;
3566         int             removed_keys = 0;
3567         int             empty_slot;
3568         
3569         data = p2->data;
3570         empty_slot = data->num_keys;
3571
3572         if ( !key )
3573                 return WERR_INVALID_PARAM;
3574         
3575         /* remove all keys */
3576
3577         if ( !strlen(key) ) {
3578         
3579                 TALLOC_FREE( data );
3580
3581                 p2->data = NULL;
3582
3583                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3584                         p2->printername ));
3585         
3586                 return WERR_OK;
3587         }
3588
3589         /* remove a specific key (and all subkeys) */
3590         
3591         for ( i=0; i<data->num_keys; i++ ) {
3592                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3593                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3594                                 data->keys[i].name));
3595                 
3596                         TALLOC_FREE( data->keys[i].name );
3597                         TALLOC_FREE( data->keys[i].values );
3598
3599                         /* mark the slot as empty */
3600
3601                         ZERO_STRUCTP( &data->keys[i] );
3602                 }
3603         }
3604
3605         /* find the first empty slot */
3606
3607         for ( i=0; i<data->num_keys; i++ ) {
3608                 if ( !data->keys[i].name ) {
3609                         empty_slot = i;
3610                         removed_keys++;
3611                         break;
3612                 }
3613         }
3614
3615         if ( i == data->num_keys )
3616                 /* nothing was removed */
3617                 return WERR_INVALID_PARAM;
3618
3619         /* move everything down */
3620         
3621         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3622                 if ( data->keys[i].name ) {
3623                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
3624                         ZERO_STRUCTP( &data->keys[i] );
3625                         empty_slot++;
3626                         removed_keys++;
3627                 }
3628         }
3629
3630         /* update count */
3631                 
3632         data->num_keys -= removed_keys;
3633
3634         /* sanity check to see if anything is left */
3635
3636         if ( !data->num_keys ) {
3637                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3638
3639                 SAFE_FREE( data->keys );
3640                 ZERO_STRUCTP( data );
3641         }
3642
3643         return WERR_OK;
3644 }
3645
3646 /****************************************************************************
3647  ***************************************************************************/
3648  
3649 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3650 {
3651         WERROR          result = WERR_OK;
3652         int             key_index;
3653         
3654         /* we must have names on non-zero length */
3655         
3656         if ( !key || !*key|| !value || !*value )
3657                 return WERR_INVALID_NAME;
3658                 
3659         /* find the printer key first */
3660
3661         key_index = lookup_printerkey( p2->data, key );
3662         if ( key_index == -1 )
3663                 return WERR_OK;
3664         
3665         /* make sure the value exists so we can return the correct error code */
3666         
3667         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3668                 return WERR_BADFILE;
3669                 
3670         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3671         
3672         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3673                 key, value ));
3674         
3675         return result;
3676 }
3677
3678 /****************************************************************************
3679  ***************************************************************************/
3680  
3681 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
3682                            uint32 type, uint8 *data, int real_len )
3683 {
3684         WERROR          result = WERR_OK;
3685         int             key_index;
3686
3687         /* we must have names on non-zero length */
3688         
3689         if ( !key || !*key|| !value || !*value )
3690                 return WERR_INVALID_NAME;
3691                 
3692         /* find the printer key first */
3693         
3694         key_index = lookup_printerkey( p2->data, key );
3695         if ( key_index == -1 )
3696                 key_index = add_new_printer_key( p2->data, key );
3697                 
3698         if ( key_index == -1 )
3699                 return WERR_NOMEM;
3700         
3701         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3702                 type, (const char *)data, real_len );
3703         
3704         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3705                 key, value, type, real_len  ));
3706
3707         return result;
3708 }
3709
3710 /****************************************************************************
3711  ***************************************************************************/
3712
3713 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3714 {
3715         int             key_index;
3716
3717         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3718                 return NULL;
3719
3720         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3721                 key, value ));
3722
3723         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3724 }
3725
3726 /****************************************************************************
3727  Unpack a list of registry values frem the TDB
3728  ***************************************************************************/
3729
3730 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3731 {
3732         int             len = 0;
3733         uint32          type;
3734         fstring string;
3735         const char *valuename = NULL;
3736         const char *keyname = NULL;
3737         char            *str;
3738         int             size;
3739         uint8           *data_p;
3740         REGISTRY_VALUE  *regval_p;
3741         int             key_index;
3742
3743         /* add the "PrinterDriverData" key first for performance reasons */
3744
3745         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3746
3747         /* loop and unpack the rest of the registry values */
3748
3749         while ( True ) {
3750
3751                 /* check to see if there are any more registry values */
3752
3753                 regval_p = NULL;
3754                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3755                 if ( !regval_p )
3756                         break;
3757
3758                 /* unpack the next regval */
3759
3760                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3761                                   string,
3762                                   &type,
3763                                   &size,
3764                                   &data_p);
3765
3766                 /* lookup for subkey names which have a type of REG_NONE */
3767                 /* there's no data with this entry */
3768
3769                 if ( type == REG_NONE ) {
3770                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3771                                 add_new_printer_key( printer_data, string );
3772                         continue;
3773                 }
3774
3775                 /*
3776                  * break of the keyname from the value name.
3777                  * Valuenames can have embedded '\'s so be careful.
3778                  * only support one level of keys.  See the
3779                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3780                  * -- jerry
3781                  */
3782
3783                 str = strchr_m( string, '\\');
3784
3785                 /* Put in "PrinterDriverData" is no key specified */
3786
3787                 if ( !str ) {
3788                         keyname = SPOOL_PRINTERDATA_KEY;
3789                         valuename = string;
3790                 }
3791                 else {
3792                         *str = '\0';
3793                         keyname = string;
3794                         valuename = str+1;
3795                 }
3796
3797                 /* see if we need a new key */
3798
3799                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3800                         key_index = add_new_printer_key( printer_data, keyname );
3801
3802                 if ( key_index == -1 ) {
3803                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3804                                 keyname));
3805                         break;
3806                 }
3807
3808                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3809
3810                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3811                    Thanks to Martin Zielinski for the hint. */
3812
3813                 if ( type == REG_BINARY &&
3814                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3815                      strequal( valuename, "objectGUID" ) )
3816                 {
3817                         struct GUID guid;
3818                         UNISTR2 unistr_guid;
3819
3820                         ZERO_STRUCT( unistr_guid );
3821
3822                         /* convert the GUID to a UNICODE string */
3823
3824                         memcpy( &guid, data_p, sizeof(struct GUID) );
3825
3826                         init_unistr2( &unistr_guid,
3827                                       smb_uuid_string(talloc_tos(), guid), 
3828                                       UNI_STR_TERMINATE );
3829
3830                         regval_ctr_addvalue( printer_data->keys[key_index].values, 
3831                                              valuename, REG_SZ,
3832                                              (const char *)unistr_guid.buffer,
3833                                              unistr_guid.uni_str_len*2 );
3834
3835                 } else {
3836                         /* add the value */
3837
3838                         regval_ctr_addvalue( printer_data->keys[key_index].values, 
3839                                              valuename, type, (const char *)data_p, 
3840                                              size );
3841                 }
3842
3843                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3844
3845         }
3846
3847         return len;
3848 }
3849
3850 /****************************************************************************
3851  ***************************************************************************/
3852
3853 static char *last_from;
3854 static char *last_to;
3855
3856 static const char *get_last_from(void)
3857 {
3858         if (!last_from) {
3859                 return "";
3860         }
3861         return last_from;
3862 }
3863
3864 static const char *get_last_to(void)
3865 {
3866         if (!last_to) {
3867                 return "";
3868         }
3869         return last_to;
3870 }
3871
3872 static bool set_last_from_to(const char *from, const char *to)
3873 {
3874         char *orig_from = last_from;
3875         char *orig_to = last_to;
3876
3877         last_from = SMB_STRDUP(from);
3878         last_to = SMB_STRDUP(to);
3879
3880         SAFE_FREE(orig_from);
3881         SAFE_FREE(orig_to);
3882
3883         if (!last_from || !last_to) {
3884                 SAFE_FREE(last_from);
3885                 SAFE_FREE(last_to);
3886                 return false;
3887         }
3888         return true;
3889 }
3890
3891 static void map_to_os2_driver(fstring drivername)
3892 {
3893         char *mapfile = lp_os2_driver_map();
3894         char **lines = NULL;
3895         int numlines = 0;
3896         int i;
3897
3898         if (!strlen(drivername))
3899                 return;
3900
3901         if (!*mapfile)
3902                 return;
3903
3904         if (strequal(drivername,get_last_from())) {
3905                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3906                         drivername,get_last_to()));
3907                 fstrcpy(drivername,get_last_to());
3908                 return;
3909         }
3910
3911         lines = file_lines_load(mapfile, &numlines,0);
3912         if (numlines == 0 || lines == NULL) {
3913                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3914                 SAFE_FREE(lines);
3915                 return;
3916         }
3917
3918         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3919
3920         for( i = 0; i < numlines; i++) {
3921                 char *nt_name = lines[i];
3922                 char *os2_name = strchr(nt_name,'=');
3923
3924                 if (!os2_name)
3925                         continue;
3926
3927                 *os2_name++ = 0;
3928
3929                 while (isspace(*nt_name))
3930                         nt_name++;
3931
3932                 if (!*nt_name || strchr("#;",*nt_name))
3933                         continue;
3934
3935                 {
3936                         int l = strlen(nt_name);
3937                         while (l && isspace(nt_name[l-1])) {
3938                                 nt_name[l-1] = 0;
3939                                 l--;
3940                         }
3941                 }
3942
3943                 while (isspace(*os2_name))
3944                         os2_name++;
3945
3946                 {
3947                         int l = strlen(os2_name);
3948                         while (l && isspace(os2_name[l-1])) {
3949                                 os2_name[l-1] = 0;
3950                                 l--;
3951                         }
3952                 }
3953
3954                 if (strequal(nt_name,drivername)) {
3955                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3956                         set_last_from_to(drivername,os2_name);
3957                         fstrcpy(drivername,os2_name);
3958                         file_lines_free(lines);
3959                         return;
3960                 }
3961         }
3962
3963         file_lines_free(lines);
3964 }
3965
3966 /****************************************************************************
3967  Get a default printer info 2 struct.
3968 ****************************************************************************/
3969 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3970 {
3971         int snum = lp_servicenumber(sharename);
3972
3973         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3974         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", 
3975                 servername, sharename);
3976         fstrcpy(info->sharename, sharename);
3977         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3978
3979         /* by setting the driver name to an empty string, a local NT admin
3980            can now run the **local** APW to install a local printer driver
3981            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3982            installed on the Samba server for NT clients --jerry */
3983 #if 0   /* JERRY --do not uncomment-- */
3984         if (!*info->drivername)
3985                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3986 #endif
3987
3988
3989         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3990
3991         strlcpy(info->comment, "", sizeof(info->comment));
3992         fstrcpy(info->printprocessor, "winprint");
3993         fstrcpy(info->datatype, "RAW");
3994
3995 #ifdef HAVE_CUPS
3996         if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {           
3997                 /* Pull the location and comment strings from cups if we don't
3998                    already have one */
3999                 if ( !strlen(info->location) || !strlen(info->comment) )
4000                         cups_pull_comment_location( info );
4001         }
4002 #endif
4003
4004         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4005
4006         info->starttime = 0; /* Minutes since 12:00am GMT */
4007         info->untiltime = 0; /* Minutes since 12:00am GMT */
4008         info->priority = 1;
4009         info->default_priority = 1;
4010         info->setuptime = (uint32)time(NULL);
4011
4012         /*
4013          * I changed this as I think it is better to have a generic
4014          * DEVMODE than to crash Win2k explorer.exe   --jerry
4015          * See the HP Deskjet 990c Win2k drivers for an example.
4016          *
4017          * However the default devmode appears to cause problems
4018          * with the HP CLJ 8500 PCL driver.  Hence the addition of
4019          * the "default devmode" parameter   --jerry 22/01/2002
4020          */
4021
4022         if (lp_default_devmode(snum)) {
4023                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4024                         goto fail;
4025                 }
4026         } else {
4027                 info->devmode = NULL;
4028         }
4029
4030         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4031                 goto fail;
4032         }
4033
4034         return WERR_OK;
4035
4036 fail:
4037         if (info->devmode)
4038                 free_nt_devicemode(&info->devmode);
4039
4040         return WERR_ACCESS_DENIED;
4041 }
4042
4043 /****************************************************************************
4044 ****************************************************************************/
4045 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
4046 {
4047         int len = 0;
4048         int snum = lp_servicenumber(sharename);
4049         TDB_DATA kbuf, dbuf;
4050         fstring printername;
4051         char adevice[MAXDEVICENAME];
4052         char *comment = NULL;
4053
4054         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4055
4056         dbuf = tdb_fetch(tdb_printers, kbuf);
4057         if (!dbuf.dptr) {
4058                 return get_a_printer_2_default(info, servername, sharename);
4059         }
4060
4061         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4062                         &info->attributes,
4063                         &info->priority,
4064                         &info->default_priority,
4065                         &info->starttime,
4066                         &info->untiltime,
4067                         &info->status,
4068                         &info->cjobs,
4069                         &info->averageppm,
4070                         &info->changeid,
4071                         &info->c_setprinter,
4072                         &info->setuptime,
4073                         info->servername,
4074                         info->printername,
4075                         info->sharename,
4076                         info->portname,
4077                         info->drivername,
4078                         &comment,
4079                         info->location,
4080                         info->sepfile,
4081                         info->printprocessor,
4082                         info->datatype,
4083                         info->parameters);
4084
4085         if (comment) {
4086                 strlcpy(info->comment, comment, sizeof(info->comment));
4087                 SAFE_FREE(comment);
4088         }
4089
4090         /* Samba has to have shared raw drivers. */
4091         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4092         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4093
4094         /* Restore the stripped strings. */
4095         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4096
4097         if ( lp_force_printername(snum) ) {
4098                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4099         } else {
4100                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4101         }
4102
4103         fstrcpy(info->printername, printername);
4104
4105 #ifdef HAVE_CUPS
4106         if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {           
4107                 /* Pull the location and comment strings from cups if we don't
4108                    already have one */
4109                 if ( !strlen(info->location) || !strlen(info->comment) )
4110                         cups_pull_comment_location( info );
4111         }
4112 #endif
4113
4114         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4115
4116         /*
4117          * Some client drivers freak out if there is a NULL devmode
4118          * (probably the driver is not checking before accessing 
4119          * the devmode pointer)   --jerry
4120          *
4121          * See comments in get_a_printer_2_default()
4122          */
4123
4124         if (lp_default_devmode(snum) && !info->devmode) {
4125                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4126                         printername));
4127                 info->devmode = construct_nt_devicemode(printername);
4128         }
4129
4130         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4131         if (info->devmode) {
4132                 fstrcpy(info->devmode->devicename, adevice);    
4133         }
4134
4135         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4136                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4137                 SAFE_FREE(dbuf.dptr);
4138                 return WERR_NOMEM;
4139         }
4140         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4141
4142         /* This will get the current RPC talloc context, but we should be
4143            passing this as a parameter... fixme... JRA ! */
4144
4145         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4146                 SAFE_FREE(dbuf.dptr);
4147                 return WERR_NOMEM;
4148         }
4149
4150         /* Fix for OS/2 drivers. */
4151
4152         if (get_remote_arch() == RA_OS2) {
4153                 map_to_os2_driver(info->drivername);
4154         }
4155
4156         SAFE_FREE(dbuf.dptr);
4157
4158         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4159                  sharename, info->printername, info->drivername));
4160
4161         return WERR_OK; 
4162 }
4163
4164 /****************************************************************************
4165  Debugging function, dump at level 6 the struct in the logs.
4166 ****************************************************************************/
4167 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4168 {
4169         uint32 result;
4170         NT_PRINTER_INFO_LEVEL_2 *info2;
4171         
4172         DEBUG(106,("Dumping printer at level [%d]\n", level));
4173         
4174         switch (level) {
4175                 case 2:
4176                 {
4177                         if (printer->info_2 == NULL)
4178                                 result=5;
4179                         else
4180                         {
4181                                 info2=printer->info_2;
4182                         
4183                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4184                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4185                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4186                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4187                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4188                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4189                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4190                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4191                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4192                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4193                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4194
4195                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4196                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4197                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4198                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4199                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4200                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4201                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4202                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4203                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4204                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4205                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4206                                 result=0;
4207                         }
4208                         break;
4209                 }
4210                 default:
4211                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4212                         result=1;
4213                         break;
4214         }
4215         
4216         return result;
4217 }
4218
4219 /****************************************************************************
4220  Update the changeid time.
4221  This is SO NASTY as some drivers need this to change, others need it
4222  static. This value will change every second, and I must hope that this
4223  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4224  UTAH ! JRA.
4225 ****************************************************************************/
4226
4227 static uint32 rev_changeid(void)
4228 {
4229         struct timeval tv;
4230
4231         get_process_uptime(&tv);
4232
4233 #if 1   /* JERRY */
4234         /* Return changeid as msec since spooler restart */
4235         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4236 #else
4237         /*
4238          * This setting seems to work well but is too untested
4239          * to replace the above calculation.  Left in for experiementation
4240          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4241          */
4242         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4243 #endif
4244 }
4245
4246
4247 /*
4248  * The function below are the high level ones.
4249  * only those ones must be called from the spoolss code.
4250  * JFM.
4251  */
4252
4253 /****************************************************************************
4254  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4255 ****************************************************************************/
4256
4257 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4258 {
4259         WERROR result;
4260         
4261         dump_a_printer(printer, level); 
4262         
4263         switch (level) {
4264                 case 2:
4265                 {
4266                         /*
4267                          * Update the changestamp.  Emperical tests show that the
4268                          * ChangeID is always updated,but c_setprinter is  
4269                          *  global spooler variable (not per printer).
4270                          */
4271
4272                         /* ChangeID **must** be increasing over the lifetime
4273                            of client's spoolss service in order for the
4274                            client's cache to show updates */
4275
4276                         printer->info_2->changeid = rev_changeid();
4277
4278                         /*
4279                          * Because one day someone will ask:
4280                          * NT->NT       An admin connection to a remote
4281                          *              printer show changes imeediately in
4282                          *              the properities dialog
4283                          *      
4284                          *              A non-admin connection will only show the
4285                          *              changes after viewing the properites page
4286                          *              2 times.  Seems to be related to a
4287                          *              race condition in the client between the spooler
4288                          *              updating the local cache and the Explorer.exe GUI
4289                          *              actually displaying the properties.
4290                          *
4291                          *              This is fixed in Win2k.  admin/non-admin
4292                          *              connections both display changes immediately.
4293                          *
4294                          * 14/12/01     --jerry
4295                          */
4296
4297                         result=update_a_printer_2(printer->info_2);
4298                         break;
4299                 }
4300                 default:
4301                         result=WERR_UNKNOWN_LEVEL;
4302                         break;
4303         }
4304
4305         return result;
4306 }
4307
4308 /****************************************************************************
4309  Initialize printer devmode & data with previously saved driver init values.
4310 ****************************************************************************/
4311
4312 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4313 {
4314         int                     len = 0;
4315         char *key = NULL;
4316         TDB_DATA                dbuf;
4317         NT_PRINTER_INFO_LEVEL_2 info;
4318
4319
4320         ZERO_STRUCT(info);
4321
4322         /*
4323          * Delete any printer data 'values' already set. When called for driver
4324          * replace, there will generally be some, but during an add printer, there
4325          * should not be any (if there are delete them).
4326          */
4327
4328         if ( info_ptr->data )
4329                 delete_all_printer_data( info_ptr, "" );
4330
4331         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4332                                 info_ptr->drivername) < 0) {
4333                 return false;
4334         }
4335
4336         dbuf = tdb_fetch_bystring(tdb_drivers, key);
4337         if (!dbuf.dptr) {
4338                 /*
4339                  * When changing to a driver that has no init info in the tdb, remove
4340                  * the previous drivers init info and leave the new on blank.
4341                  */
4342                 free_nt_devicemode(&info_ptr->devmode);
4343                 SAFE_FREE(key);
4344                 return false;
4345         }
4346
4347         SAFE_FREE(key);
4348         /*
4349          * Get the saved DEVMODE..
4350          */
4351
4352         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4353
4354         /*
4355          * The saved DEVMODE contains the devicename from the printer used during
4356          * the initialization save. Change it to reflect the new printer.
4357          */
4358
4359         if ( info.devmode ) {
4360                 ZERO_STRUCT(info.devmode->devicename);
4361                 fstrcpy(info.devmode->devicename, info_ptr->printername);
4362         }
4363
4364         /*
4365          * NT/2k does not change out the entire DeviceMode of a printer
4366          * when changing the driver.  Only the driverextra, private, &
4367          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
4368          *
4369          * Later examination revealed that Windows NT/2k does reset the
4370          * the printer's device mode, bit **only** when you change a
4371          * property of the device mode such as the page orientation.
4372          * --jerry
4373          */
4374
4375
4376         /* Bind the saved DEVMODE to the new the printer */
4377
4378         free_nt_devicemode(&info_ptr->devmode);
4379         info_ptr->devmode = info.devmode;
4380
4381         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4382                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4383
4384         /* Add the printer data 'values' to the new printer */
4385
4386         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4387                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4388                 return False;
4389         }
4390
4391         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4392
4393         SAFE_FREE(dbuf.dptr);
4394
4395         return true;
4396 }
4397
4398 /****************************************************************************
4399  Initialize printer devmode & data with previously saved driver init values.
4400  When a printer is created using AddPrinter, the drivername bound to the
4401  printer is used to lookup previously saved driver initialization info, which
4402  is bound to the new printer.
4403 ****************************************************************************/
4404
4405 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4406 {
4407         bool result = False;
4408
4409         switch (level) {
4410                 case 2:
4411                         result = set_driver_init_2(printer->info_2);
4412                         break;
4413
4414                 default:
4415                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4416                                 level));
4417                         break;
4418         }
4419
4420         return result;
4421 }
4422
4423 /****************************************************************************
4424  Delete driver init data stored for a specified driver
4425 ****************************************************************************/
4426
4427 bool del_driver_init(char *drivername)
4428 {
4429         char *key;
4430         bool ret;
4431
4432         if (!drivername || !*drivername) {
4433                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4434                 return false;
4435         }
4436
4437         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4438                 return false;
4439         }
4440
4441         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4442                                 drivername));
4443
4444         ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4445         SAFE_FREE(key);
4446         return ret;
4447 }
4448
4449 /****************************************************************************
4450  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
4451  in the tdb. Note: this is different from the driver entry and the printer
4452  entry. There should be a single driver init entry for each driver regardless
4453  of whether it was installed from NT or 2K. Technically, they should be
4454  different, but they work out to the same struct.
4455 ****************************************************************************/
4456
4457 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4458 {
4459         char *key = NULL;
4460         uint8 *buf;
4461         int buflen, len, ret;
4462         int retlen;
4463         TDB_DATA dbuf;
4464
4465         buf = NULL;
4466         buflen = 0;
4467
4468  again:
4469         len = 0;
4470         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4471
4472         retlen = pack_values( info->data, buf+len, buflen-len );
4473         if (retlen == -1) {
4474                 ret = -1;
4475                 goto done;
4476         }
4477         len += retlen;
4478
4479         if (buflen < len) {
4480                 buf = (uint8 *)SMB_REALLOC(buf, len);
4481                 if (!buf) {
4482                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4483                         ret = -1;
4484                         goto done;
4485                 }
4486                 buflen = len;
4487                 goto again;
4488         }
4489
4490         SAFE_FREE(key);
4491         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4492                 ret = (uint32)-1;
4493                 goto done;
4494         }
4495
4496         dbuf.dptr = buf;
4497         dbuf.dsize = len;
4498
4499         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4500
4501 done:
4502         if (ret == -1)
4503                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4504
4505         SAFE_FREE(buf);
4506
4507         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4508                  info->sharename, info->drivername));
4509
4510         return ret;
4511 }
4512
4513 /****************************************************************************
4514  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4515 ****************************************************************************/
4516
4517 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4518 {
4519         uint32 result;
4520         
4521         dump_a_printer(printer, level); 
4522         
4523         switch (level) {
4524                 case 2:
4525                         result = update_driver_init_2(printer->info_2);
4526                         break;
4527                 default:
4528                         result = 1;
4529                         break;
4530         }
4531         
4532         return result;
4533 }
4534
4535 /****************************************************************************
4536  Convert the printer data value, a REG_BINARY array, into an initialization 
4537  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4538  got to keep the endians happy :).
4539 ****************************************************************************/
4540
4541 static bool convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4542 {
4543         bool       result = False;
4544         prs_struct ps;
4545         DEVICEMODE devmode;
4546
4547         ZERO_STRUCT(devmode);
4548
4549         prs_init(&ps, 0, ctx, UNMARSHALL);
4550         ps.data_p      = (char *)data;
4551         ps.buffer_size = data_len;
4552
4553         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4554                 result = convert_devicemode("", &devmode, &nt_devmode);
4555         else
4556                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4557
4558         return result;
4559 }
4560
4561 /****************************************************************************
4562  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4563
4564  1. Use the driver's config DLL to this UNC printername and:
4565     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4566     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4567  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4568
4569  The last step triggers saving the "driver initialization" information for
4570  this printer into the tdb. Later, new printers that use this driver will
4571  have this initialization information bound to them. This simulates the
4572  driver initialization, as if it had run on the Samba server (as it would
4573  have done on NT).
4574
4575  The Win32 client side code requirement sucks! But until we can run arbitrary
4576  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4577  
4578  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4579  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4580  about it and you will realize why.  JRR 010720
4581 ****************************************************************************/
4582
4583 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4584 {
4585         WERROR        status       = WERR_OK;
4586         TALLOC_CTX    *ctx         = NULL;
4587         NT_DEVICEMODE *nt_devmode  = NULL;
4588         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4589         
4590         /*
4591          * When the DEVMODE is already set on the printer, don't try to unpack it.
4592          */
4593         DEBUG(8,("save_driver_init_2: Enter...\n"));
4594         
4595         if ( !printer->info_2->devmode && data_len ) {
4596                 /*
4597                  * Set devmode on printer info, so entire printer initialization can be
4598                  * saved to tdb.
4599                  */
4600
4601                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4602                         return WERR_NOMEM;
4603
4604                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4605                         status = WERR_NOMEM;
4606                         goto done;
4607                 }
4608         
4609                 ZERO_STRUCTP(nt_devmode);
4610
4611                 /*
4612                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4613                  * Convert it to to a devmode structure
4614                  */
4615                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4616                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4617                         status = WERR_INVALID_PARAM;
4618                         goto done;
4619                 }
4620
4621                 printer->info_2->devmode = nt_devmode;
4622         }
4623
4624         /*
4625          * Pack up and add (or update) the DEVMODE and any current printer data to
4626          * a 'driver init' element in the tdb
4627          * 
4628          */
4629
4630         if ( update_driver_init(printer, 2) != 0 ) {
4631                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4632                 status = WERR_NOMEM;
4633                 goto done;
4634         }
4635         
4636         /*
4637          * If driver initialization info was successfully saved, set the current 
4638          * printer to match it. This allows initialization of the current printer 
4639          * as well as the driver.
4640          */
4641         status = mod_a_printer(printer, 2);
4642         if (!W_ERROR_IS_OK(status)) {
4643                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4644                                   printer->info_2->printername));
4645         }
4646         
4647   done:
4648         talloc_destroy(ctx);
4649         free_nt_devicemode( &nt_devmode );
4650         
4651         printer->info_2->devmode = tmp_devmode;
4652
4653         return status;
4654 }
4655
4656 /****************************************************************************
4657  Update the driver init info (DEVMODE and specifics) for a printer
4658 ****************************************************************************/
4659
4660 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4661 {
4662         WERROR status = WERR_OK;
4663         
4664         switch (level) {
4665                 case 2:
4666                         status = save_driver_init_2( printer, data, data_len );
4667                         break;
4668                 default:
4669                         status = WERR_UNKNOWN_LEVEL;
4670                         break;
4671         }
4672         
4673         return status;
4674 }
4675
4676 /****************************************************************************
4677  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4678
4679  Previously the code had a memory allocation problem because it always
4680  used the TALLOC_CTX from the Printer_entry*.   This context lasts 
4681  as a long as the original handle is open.  So if the client made a lot 
4682  of getprinter[data]() calls, the memory usage would climb.  Now we use
4683  a short lived TALLOC_CTX for printer_info_2 objects returned.  We 
4684  still use the Printer_entry->ctx for maintaining the cache copy though
4685  since that object must live as long as the handle by definition.  
4686                                                     --jerry
4687
4688 ****************************************************************************/
4689
4690 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
4691                         const char *sharename)
4692 {
4693         WERROR result;
4694         fstring servername;
4695         
4696         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4697
4698         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4699                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4700                 return WERR_NOMEM;
4701         }
4702
4703         switch (level) {
4704                 case 2:
4705                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4706                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4707                                 TALLOC_FREE( *pp_printer );
4708                                 return WERR_NOMEM;
4709                         }
4710
4711                         if ( print_hnd ) 
4712                                 fstrcpy( servername, print_hnd->servername );
4713                         else {
4714                                 fstrcpy( servername, "%L" );
4715                                 standard_sub_basic( "", "", servername,
4716                                                     sizeof(servername)-1 );
4717                         }
4718
4719                         result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4720         
4721                         
4722                         /* we have a new printer now.  Save it with this handle */
4723                         
4724                         if ( !W_ERROR_IS_OK(result) ) {
4725                                 TALLOC_FREE( *pp_printer );
4726                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 
4727                                         sharename, (unsigned int)level, dos_errstr(result)));
4728                                 return result;
4729                         }
4730
4731                         dump_a_printer( *pp_printer, level);
4732                         
4733                         break;
4734                         
4735                 default:
4736                         TALLOC_FREE( *pp_printer );
4737                         return WERR_UNKNOWN_LEVEL;
4738         }
4739         
4740         return WERR_OK;
4741 }
4742
4743 /****************************************************************************
4744  Deletes a NT_PRINTER_INFO_LEVEL struct.
4745 ****************************************************************************/
4746
4747 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4748 {
4749         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4750
4751         if ( !printer )
4752                 return 0;
4753         
4754         switch (level) {
4755                 case 2:
4756                         if ( printer->info_2 ) 
4757                                 free_nt_printer_info_level_2(&printer->info_2);
4758                         break;
4759
4760                 default:
4761                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4762                         return 1;
4763         }
4764
4765         TALLOC_FREE(*pp_printer);
4766
4767         return 0;
4768 }
4769
4770 /****************************************************************************
4771 ****************************************************************************/
4772 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4773 {
4774         uint32 result;
4775         DEBUG(104,("adding a printer at level [%d]\n", level));
4776         dump_a_printer_driver(driver, level);
4777         
4778         switch (level) {
4779                 case 3:
4780                         result=add_a_printer_driver_3(driver.info_3);
4781                         break;
4782
4783                 case 6:
4784                         result=add_a_printer_driver_6(driver.info_6);
4785                         break;
4786
4787                 default:
4788                         result=1;
4789                         break;
4790         }
4791         
4792         return result;
4793 }
4794 /****************************************************************************
4795 ****************************************************************************/
4796
4797 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4798                             fstring drivername, const char *architecture, uint32 version)
4799 {
4800         WERROR result;
4801         
4802         switch (level) {
4803                 case 3:
4804                         /* Sometime we just want any version of the driver */
4805                         
4806                         if ( version == DRIVER_ANY_VERSION ) {
4807                                 /* look for Win2k first and then for NT4 */
4808                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4809                                                 architecture, 3);
4810                                                 
4811                                 if ( !W_ERROR_IS_OK(result) ) {
4812                                         result = get_a_printer_driver_3( &driver->info_3, 
4813                                                         drivername, architecture, 2 );
4814                                 }
4815                         } else {
4816                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4817                                         architecture, version);                         
4818                         }
4819                         break;
4820                         
4821                 default:
4822                         result=W_ERROR(1);
4823                         break;
4824         }
4825         
4826         if (W_ERROR_IS_OK(result))
4827                 dump_a_printer_driver(*driver, level);
4828                 
4829         return result;
4830 }
4831
4832 /****************************************************************************
4833 ****************************************************************************/
4834 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4835 {
4836         uint32 result;
4837         
4838         switch (level) {
4839                 case 3:
4840                 {
4841                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4842                         if (driver.info_3 != NULL)
4843                         {
4844                                 info3=driver.info_3;
4845                                 SAFE_FREE(info3->dependentfiles);
4846                                 ZERO_STRUCTP(info3);
4847                                 SAFE_FREE(info3);
4848                                 result=0;
4849                         } else {
4850                                 result=4;
4851                         }
4852                         break;
4853                 }
4854                 case 6:
4855                 {
4856                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4857                         if (driver.info_6 != NULL) {
4858                                 info6=driver.info_6;
4859                                 SAFE_FREE(info6->dependentfiles);
4860                                 SAFE_FREE(info6->previousnames);
4861                                 ZERO_STRUCTP(info6);
4862                                 SAFE_FREE(info6);
4863                                 result=0;
4864                         } else {
4865                                 result=4;
4866                         }
4867                         break;
4868                 }
4869                 default:
4870                         result=1;
4871                         break;
4872         }
4873         return result;
4874 }
4875
4876
4877 /****************************************************************************
4878   Determine whether or not a particular driver is currently assigned
4879   to a printer
4880 ****************************************************************************/
4881
4882 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4883 {
4884         int snum;
4885         int n_services = lp_numservices();
4886         NT_PRINTER_INFO_LEVEL *printer = NULL;
4887         bool in_use = False;
4888
4889         if ( !info_3 ) 
4890                 return False;
4891
4892         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4893         
4894         /* loop through the printers.tdb and check for the drivername */
4895         
4896         for (snum=0; snum<n_services && !in_use; snum++) {
4897                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4898                         continue;
4899                 
4900                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4901                         continue;
4902                 
4903                 if ( strequal(info_3->name, printer->info_2->drivername) ) 
4904                         in_use = True;
4905                 
4906                 free_a_printer( &printer, 2 );
4907         }
4908         
4909         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4910         
4911         if ( in_use ) {
4912                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4913                 WERROR werr;
4914                 
4915                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4916                 
4917                 /* we can still remove the driver if there is one of 
4918                    "Windows NT x86" version 2 or 3 left */
4919                    
4920                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4921                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );                       
4922                 }
4923                 else {
4924                         switch ( info_3->cversion ) {
4925                         case 2:
4926                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4927                                 break;
4928                         case 3: 
4929                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4930                                 break;
4931                         default:
4932                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 
4933                                         info_3->cversion));
4934                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4935                                 break;
4936                         }
4937                 }
4938
4939                 /* now check the error code */
4940                                 
4941                 if ( W_ERROR_IS_OK(werr) ) {
4942                         /* it's ok to remove the driver, we have other architctures left */
4943                         in_use = False;
4944                         free_a_printer_driver( d, 3 );
4945                 }
4946         }
4947         
4948         /* report that the driver is not in use by default */
4949         
4950         return in_use;
4951 }
4952
4953
4954 /**********************************************************************
4955  Check to see if a ogiven file is in use by *info
4956  *********************************************************************/
4957  
4958 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4959 {
4960         int i = 0;
4961         
4962         if ( !info )
4963                 return False;
4964                 
4965         if ( strequal(file, info->driverpath) )
4966                 return True;
4967
4968         if ( strequal(file, info->datafile) )
4969                 return True;
4970
4971         if ( strequal(file, info->configfile) )
4972                 return True;
4973
4974         if ( strequal(file, info->helpfile) )
4975                 return True;
4976         
4977         /* see of there are any dependent files to examine */
4978         
4979         if ( !info->dependentfiles )
4980                 return False;
4981         
4982         while ( *info->dependentfiles[i] ) {
4983                 if ( strequal(file, info->dependentfiles[i]) )
4984                         return True;
4985                 i++;
4986         }
4987         
4988         return False;
4989
4990 }
4991
4992 /**********************************************************************
4993  Utility function to remove the dependent file pointed to by the 
4994  input parameter from the list 
4995  *********************************************************************/
4996
4997 static void trim_dependent_file( fstring files[], int idx )
4998 {
4999         
5000         /* bump everything down a slot */
5001
5002         while( *files[idx+1] ) {
5003                 fstrcpy( files[idx], files[idx+1] );
5004                 idx++;
5005         }
5006         
5007         *files[idx] = '\0';
5008
5009         return; 
5010 }
5011
5012 /**********************************************************************
5013  Check if any of the files used by src are also used by drv 
5014  *********************************************************************/
5015
5016 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
5017                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
5018 {
5019         bool    in_use = False;
5020         int     i = 0;
5021         
5022         if ( !src || !drv )
5023                 return False;
5024                 
5025         /* check each file.  Remove it from the src structure if it overlaps */
5026         
5027         if ( drv_file_in_use(src->driverpath, drv) ) {
5028                 in_use = True;
5029                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
5030                 fstrcpy( src->driverpath, "" );
5031         }
5032                 
5033         if ( drv_file_in_use(src->datafile, drv) ) {
5034                 in_use = True;
5035                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
5036                 fstrcpy( src->datafile, "" );
5037         }
5038                 
5039         if ( drv_file_in_use(src->configfile, drv) ) {
5040                 in_use = True;
5041                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5042                 fstrcpy( src->configfile, "" );
5043         }
5044                 
5045         if ( drv_file_in_use(src->helpfile, drv) ) {
5046                 in_use = True;
5047                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5048                 fstrcpy( src->helpfile, "" );
5049         }
5050         
5051         /* are there any dependentfiles to examine? */
5052         
5053         if ( !src->dependentfiles )
5054                 return in_use;
5055                 
5056         while ( *src->dependentfiles[i] ) {
5057                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5058                         in_use = True;
5059                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5060                         trim_dependent_file( src->dependentfiles, i );
5061                 } else
5062                         i++;
5063         }               
5064                 
5065         return in_use;
5066 }
5067
5068 /****************************************************************************
5069   Determine whether or not a particular driver files are currently being 
5070   used by any other driver.  
5071   
5072   Return value is True if any files were in use by other drivers
5073   and False otherwise.
5074   
5075   Upon return, *info has been modified to only contain the driver files
5076   which are not in use
5077 ****************************************************************************/
5078
5079 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5080 {
5081         int                             i;
5082         int                             ndrivers;
5083         uint32                          version;
5084         fstring                         *list = NULL;
5085         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5086         
5087         if ( !info )
5088                 return False;
5089         
5090         version = info->cversion;
5091         
5092         /* loop over all driver versions */
5093         
5094         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5095         
5096         /* get the list of drivers */
5097                 
5098         list = NULL;
5099         ndrivers = get_ntdrivers(&list, info->environment, version);
5100                 
5101         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
5102                 ndrivers, info->environment, version));
5103
5104         /* check each driver for overlap in files */
5105                 
5106         for (i=0; i<ndrivers; i++) {
5107                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5108                         
5109                 ZERO_STRUCT(driver);
5110                         
5111                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5112                         SAFE_FREE(list);
5113                         return True;
5114                 }
5115                         
5116                 /* check if d2 uses any files from d1 */
5117                 /* only if this is a different driver than the one being deleted */
5118                         
5119                 if ( !strequal(info->name, driver.info_3->name) ) {
5120                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
5121                                 free_a_printer_driver(driver, 3);
5122                                 SAFE_FREE( list );
5123                                 return True;
5124                         }
5125                 }
5126
5127                 free_a_printer_driver(driver, 3);
5128         }
5129
5130         SAFE_FREE(list);
5131
5132         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5133
5134         driver.info_3 = info;
5135
5136         if ( DEBUGLEVEL >= 20 )
5137                 dump_a_printer_driver( driver, 3 );
5138
5139         return False;
5140 }
5141
5142 /****************************************************************************
5143   Actually delete the driver files.  Make sure that
5144   printer_driver_files_in_use() return False before calling
5145   this.
5146 ****************************************************************************/
5147
5148 static bool delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
5149 {
5150         int i = 0;
5151         char *s;
5152         const char *file;
5153         connection_struct *conn;
5154         DATA_BLOB null_pw;
5155         NTSTATUS nt_status;
5156         fstring res_type;
5157         SMB_STRUCT_STAT  st;
5158
5159         if ( !info_3 )
5160                 return False;
5161
5162         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5163
5164         /*
5165          * Connect to the print$ share under the same account as the
5166          * user connected to the rpc pipe. Note we must be root to
5167          * do this.
5168          */
5169
5170         null_pw = data_blob_null;
5171         fstrcpy(res_type, "A:");
5172         become_root();
5173         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
5174         unbecome_root();
5175
5176         if ( !conn ) {
5177                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
5178                 return False;
5179         }
5180
5181         if ( !CAN_WRITE(conn) ) {
5182                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5183                 return False;
5184         }
5185
5186         /* Save who we are - we are temporarily becoming the connection user. */
5187
5188         if ( !become_user(conn, conn->vuid) ) {
5189                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
5190                 return False;
5191         }
5192
5193         /* now delete the files; must strip the '\print$' string from
5194            fron of path                                                */
5195
5196         if ( *info_3->driverpath ) {
5197                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5198                         file = s;
5199                         driver_unix_convert(conn,file,&st);
5200                         DEBUG(10,("deleting driverfile [%s]\n", s));
5201                         unlink_internals(conn, NULL, 0, file, False);
5202                 }
5203         }
5204
5205         if ( *info_3->configfile ) {
5206                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5207                         file = s;
5208                         driver_unix_convert(conn,file,&st);
5209                         DEBUG(10,("deleting configfile [%s]\n", s));
5210                         unlink_internals(conn, NULL, 0, file, False);
5211                 }
5212         }
5213
5214         if ( *info_3->datafile ) {
5215                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5216                         file = s;
5217                         driver_unix_convert(conn,file,&st);
5218                         DEBUG(10,("deleting datafile [%s]\n", s));
5219                         unlink_internals(conn, NULL, 0, file, False);
5220                 }
5221         }
5222
5223         if ( *info_3->helpfile ) {
5224                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5225                         file = s;
5226                         driver_unix_convert(conn,file,&st);
5227                         DEBUG(10,("deleting helpfile [%s]\n", s));
5228                         unlink_internals(conn, NULL, 0, file, False);
5229                 }
5230         }
5231
5232         /* check if we are done removing files */
5233
5234         if ( info_3->dependentfiles ) {
5235                 while ( info_3->dependentfiles[i][0] ) {
5236                         char *p;
5237
5238                         /* bypass the "\print$" portion of the path */
5239
5240                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5241                                 file = p;
5242                                 driver_unix_convert(conn,file,&st);
5243                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5244                                 unlink_internals(conn, NULL, 0, file, False);
5245                         }
5246
5247                         i++;
5248                 }
5249         }
5250
5251         unbecome_user();
5252
5253         return true;
5254 }
5255
5256 /****************************************************************************
5257  Remove a printer driver from the TDB.  This assumes that the the driver was
5258  previously looked up.
5259  ***************************************************************************/
5260
5261 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5262                               uint32 version, bool delete_files )
5263 {
5264         char *key = NULL;
5265         const char     *arch;
5266         TDB_DATA        dbuf;
5267         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
5268
5269         /* delete the tdb data first */
5270
5271         arch = get_short_archi(info_3->environment);
5272         if (!arch) {
5273                 return WERR_UNKNOWN_PRINTER_DRIVER;
5274         }
5275         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5276                         arch, version, info_3->name) < 0) {
5277                 return WERR_NOMEM;
5278         }
5279
5280         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5281                 key, delete_files ? "TRUE" : "FALSE" ));
5282
5283         ctr.info_3 = info_3;
5284         dump_a_printer_driver( ctr, 3 );
5285
5286         /* check if the driver actually exists for this environment */
5287
5288         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5289         if ( !dbuf.dptr ) {
5290                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5291                 SAFE_FREE(key);
5292                 return WERR_UNKNOWN_PRINTER_DRIVER;
5293         }
5294
5295         SAFE_FREE( dbuf.dptr );
5296
5297         /* ok... the driver exists so the delete should return success */
5298
5299         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5300                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5301                 SAFE_FREE(key);
5302                 return WERR_ACCESS_DENIED;
5303         }
5304
5305         /*
5306          * now delete any associated files if delete_files == True
5307          * even if this part failes, we return succes because the
5308          * driver doesn not exist any more
5309          */
5310
5311         if ( delete_files )
5312                 delete_driver_files( info_3, user );
5313
5314         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5315         SAFE_FREE(key);
5316
5317         return WERR_OK;
5318 }
5319
5320 /****************************************************************************
5321  Store a security desc for a printer.
5322 ****************************************************************************/
5323
5324 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5325 {
5326         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5327         SEC_DESC_BUF *old_secdesc_ctr = NULL;
5328         prs_struct ps;
5329         TALLOC_CTX *mem_ctx = NULL;
5330         TDB_DATA kbuf;
5331         WERROR status;
5332
5333         mem_ctx = talloc_init("nt_printing_setsec");
5334         if (mem_ctx == NULL)
5335                 return WERR_NOMEM;
5336
5337         /* The old owner and group sids of the security descriptor are not
5338            present when new ACEs are added or removed by changing printer
5339            permissions through NT.  If they are NULL in the new security
5340            descriptor then copy them over from the old one. */
5341
5342         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5343                 DOM_SID *owner_sid, *group_sid;
5344                 SEC_ACL *dacl, *sacl;
5345                 SEC_DESC *psd = NULL;
5346                 size_t size;
5347
5348                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5349                         status = WERR_NOMEM;
5350                         goto out;
5351                 }
5352
5353                 /* Pick out correct owner and group sids */
5354
5355                 owner_sid = secdesc_ctr->sd->owner_sid ?
5356                         secdesc_ctr->sd->owner_sid :
5357                         old_secdesc_ctr->sd->owner_sid;
5358
5359                 group_sid = secdesc_ctr->sd->group_sid ?
5360                         secdesc_ctr->sd->group_sid :
5361                         old_secdesc_ctr->sd->group_sid;
5362
5363                 dacl = secdesc_ctr->sd->dacl ?
5364                         secdesc_ctr->sd->dacl :
5365                         old_secdesc_ctr->sd->dacl;
5366
5367                 sacl = secdesc_ctr->sd->sacl ?
5368                         secdesc_ctr->sd->sacl :
5369                         old_secdesc_ctr->sd->sacl;
5370
5371                 /* Make a deep copy of the security descriptor */
5372
5373                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5374                                     owner_sid, group_sid,
5375                                     sacl,
5376                                     dacl,
5377                                     &size);
5378
5379                 if (!psd) {
5380                         status = WERR_NOMEM;
5381                         goto out;
5382                 }
5383
5384                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5385         }
5386
5387         if (!new_secdesc_ctr) {
5388                 new_secdesc_ctr = secdesc_ctr;
5389         }
5390
5391         /* Store the security descriptor in a tdb */
5392
5393         prs_init(&ps,
5394                  (uint32)ndr_size_security_descriptor(new_secdesc_ctr->sd, 0)
5395                  + sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5396
5397         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5398                              &ps, 1)) {
5399                 status = WERR_BADFUNC;
5400                 goto out;
5401         }
5402
5403         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5404
5405         if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5406                 status = WERR_OK;
5407         } else {
5408                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5409                 status = WERR_BADFUNC;
5410         }
5411
5412         /* Free malloc'ed memory */
5413
5414  out:
5415
5416         prs_mem_free(&ps);
5417         if (mem_ctx)
5418                 talloc_destroy(mem_ctx);
5419         return status;
5420 }
5421
5422 /****************************************************************************
5423  Construct a default security descriptor buffer for a printer.
5424 ****************************************************************************/
5425
5426 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5427 {
5428         SEC_ACE ace[5]; /* max number of ace entries */
5429         int i = 0;
5430         SEC_ACCESS sa;
5431         SEC_ACL *psa = NULL;
5432         SEC_DESC_BUF *sdb = NULL;
5433         SEC_DESC *psd = NULL;
5434         DOM_SID adm_sid;
5435         size_t sd_size;
5436
5437         /* Create an ACE where Everyone is allowed to print */
5438
5439         init_sec_access(&sa, PRINTER_ACE_PRINT);
5440         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5441                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5442
5443         /* Add the domain admins group if we are a DC */
5444         
5445         if ( IS_DC ) {
5446                 DOM_SID domadmins_sid;
5447                 
5448                 sid_copy(&domadmins_sid, get_global_sam_sid());
5449                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5450                 
5451                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5452                 init_sec_ace(&ace[i++], &domadmins_sid, 
5453                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5454                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5455                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5456                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5457         }
5458         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5459                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5460
5461                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5462                 init_sec_ace(&ace[i++], &adm_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++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5466                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5467         }
5468
5469         /* add BUILTIN\Administrators as FULL CONTROL */
5470
5471         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5472         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5473                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5474                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5475         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5476                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5477                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5478
5479         /* Make the security descriptor owned by the BUILTIN\Administrators */
5480
5481         /* The ACL revision number in rpc_secdesc.h differs from the one
5482            created by NT when setting ACE entries in printer
5483            descriptors.  NT4 complains about the property being edited by a
5484            NT5 machine. */
5485
5486         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5487                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5488                         &global_sid_Builtin_Administrators, 
5489                         &global_sid_Builtin_Administrators,
5490                         NULL, psa, &sd_size);
5491         }
5492
5493         if (!psd) {
5494                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5495                 return NULL;
5496         }
5497
5498         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5499
5500         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5501                  (unsigned int)sd_size));
5502
5503         return sdb;
5504 }
5505
5506 /****************************************************************************
5507  Get a security desc for a printer.
5508 ****************************************************************************/
5509
5510 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5511 {
5512         prs_struct ps;
5513         TDB_DATA kbuf;
5514         char *temp;
5515
5516         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5517                 sharename = temp + 1;
5518         }
5519
5520         ZERO_STRUCT(ps);
5521
5522         /* Fetch security descriptor from tdb */
5523
5524         kbuf = make_printers_secdesc_tdbkey(ctx, sharename  );
5525
5526         if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5527             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5528
5529                 prs_mem_free(&ps);
5530
5531                 DEBUG(4,("using default secdesc for %s\n", sharename));
5532
5533                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5534                         return False;
5535                 }
5536
5537                 /* Save default security descriptor for later */
5538
5539                 prs_init(&ps, (uint32)ndr_size_security_descriptor((*secdesc_ctr)->sd, 0) +
5540                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5541
5542                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5543                         tdb_prs_store(tdb_printers, kbuf, &ps);
5544                 }
5545
5546                 prs_mem_free(&ps);
5547
5548                 return True;
5549         }
5550
5551         prs_mem_free(&ps);
5552
5553         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5554            this security descriptor has been created when winbindd was
5555            down.  Take ownership of security descriptor. */
5556
5557         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5558                 DOM_SID owner_sid;
5559
5560                 /* Change sd owner to workgroup administrator */
5561
5562                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5563                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5564                         SEC_DESC *psd = NULL;
5565                         size_t size;
5566
5567                         /* Create new sd */
5568
5569                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5570
5571                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5572                                             &owner_sid,
5573                                             (*secdesc_ctr)->sd->group_sid,
5574                                             (*secdesc_ctr)->sd->sacl,
5575                                             (*secdesc_ctr)->sd->dacl,
5576                                             &size);
5577
5578                         if (!psd) {
5579                                 return False;
5580                         }
5581
5582                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5583                         if (!new_secdesc_ctr) {
5584                                 return False;
5585                         }
5586
5587                         /* Swap with other one */
5588
5589                         *secdesc_ctr = new_secdesc_ctr;
5590
5591                         /* Set it */
5592
5593                         nt_printing_setsec(sharename, *secdesc_ctr);
5594                 }
5595         }
5596
5597         if (DEBUGLEVEL >= 10) {
5598                 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5599                 int i;
5600
5601                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5602                            sharename, the_acl->num_aces));
5603
5604                 for (i = 0; i < the_acl->num_aces; i++) {
5605                         DEBUG(10, ("%s %d %d 0x%08x\n",
5606                                    sid_string_dbg(&the_acl->aces[i].trustee),
5607                                    the_acl->aces[i].type, the_acl->aces[i].flags, 
5608                                    the_acl->aces[i].access_mask)); 
5609                 }
5610         }
5611
5612         return True;
5613 }
5614
5615 /* error code:
5616         0: everything OK
5617         1: level not implemented
5618         2: file doesn't exist
5619         3: can't allocate memory
5620         4: can't free memory
5621         5: non existant struct
5622 */
5623
5624 /*
5625         A printer and a printer driver are 2 different things.
5626         NT manages them separatelly, Samba does the same.
5627         Why ? Simply because it's easier and it makes sense !
5628         
5629         Now explanation: You have 3 printers behind your samba server,
5630         2 of them are the same make and model (laser A and B). But laser B
5631         has an 3000 sheet feeder and laser A doesn't such an option.
5632         Your third printer is an old dot-matrix model for the accounting :-).
5633         
5634         If the /usr/local/samba/lib directory (default dir), you will have
5635         5 files to describe all of this.
5636         
5637         3 files for the printers (1 by printer):
5638                 NTprinter_laser A
5639                 NTprinter_laser B
5640                 NTprinter_accounting
5641         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5642                 NTdriver_printer model X
5643                 NTdriver_printer model Y
5644
5645 jfm: I should use this comment for the text file to explain
5646         same thing for the forms BTW.
5647         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5648
5649 */
5650
5651 /* Convert generic access rights to printer object specific access rights.
5652    It turns out that NT4 security descriptors use generic access rights and
5653    NT5 the object specific ones. */
5654
5655 void map_printer_permissions(SEC_DESC *sd)
5656 {
5657         int i;
5658
5659         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5660                 se_map_generic(&sd->dacl->aces[i].access_mask,
5661                                &printer_generic_mapping);
5662         }
5663 }
5664
5665 /****************************************************************************
5666  Check a user has permissions to perform the given operation.  We use the
5667  permission constants defined in include/rpc_spoolss.h to check the various
5668  actions we perform when checking printer access.
5669
5670    PRINTER_ACCESS_ADMINISTER:
5671        print_queue_pause, print_queue_resume, update_printer_sec,
5672        update_printer, spoolss_addprinterex_level_2,
5673        _spoolss_setprinterdata
5674
5675    PRINTER_ACCESS_USE:
5676        print_job_start
5677
5678    JOB_ACCESS_ADMINISTER:
5679        print_job_delete, print_job_pause, print_job_resume,
5680        print_queue_purge
5681
5682   Try access control in the following order (for performance reasons):
5683     1)  root ans SE_PRINT_OPERATOR can do anything (easy check) 
5684     2)  check security descriptor (bit comparisons in memory)
5685     3)  "printer admins" (may result in numerous calls to winbind)
5686
5687  ****************************************************************************/
5688 bool print_access_check(struct current_user *user, int snum, int access_type)
5689 {
5690         SEC_DESC_BUF *secdesc = NULL;
5691         uint32 access_granted;
5692         NTSTATUS status;
5693         bool result;
5694         const char *pname;
5695         TALLOC_CTX *mem_ctx = NULL;
5696         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5697         
5698         /* If user is NULL then use the current_user structure */
5699
5700         if (!user)
5701                 user = &current_user;
5702
5703         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5704
5705         if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5706                 return True;
5707         }
5708
5709         /* Get printer name */
5710
5711         pname = PRINTERNAME(snum);
5712
5713         if (!pname || !*pname) {
5714                 errno = EACCES;
5715                 return False;
5716         }
5717
5718         /* Get printer security descriptor */
5719
5720         if(!(mem_ctx = talloc_init("print_access_check"))) {
5721                 errno = ENOMEM;
5722                 return False;
5723         }
5724
5725         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5726                 talloc_destroy(mem_ctx);
5727                 errno = ENOMEM;
5728                 return False;
5729         }
5730
5731         if (access_type == JOB_ACCESS_ADMINISTER) {
5732                 SEC_DESC_BUF *parent_secdesc = secdesc;
5733
5734                 /* Create a child security descriptor to check permissions
5735                    against.  This is because print jobs are child objects
5736                    objects of a printer. */
5737
5738                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5739
5740                 if (!secdesc) {
5741                         talloc_destroy(mem_ctx);
5742                         errno = ENOMEM;
5743                         return False;
5744                 }
5745
5746                 /* Now this is the bit that really confuses me.  The access
5747                    type needs to be changed from JOB_ACCESS_ADMINISTER to
5748                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
5749                    to do with the child (job) object becoming like a
5750                    printer??  -tpot */
5751
5752                 access_type = PRINTER_ACCESS_ADMINISTER;
5753         }
5754         
5755         /* Check access */
5756         
5757         map_printer_permissions(secdesc->sd);
5758
5759         result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5760                                  &access_granted, &status);
5761
5762         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5763
5764         /* see if we need to try the printer admin list */
5765
5766         if ((access_granted == 0) &&
5767             (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5768                                          user->nt_user_token,
5769                                          lp_printer_admin(snum)))) {
5770                 talloc_destroy(mem_ctx);
5771                 return True;
5772         }
5773
5774         talloc_destroy(mem_ctx);
5775         
5776         if (!result) {
5777                 errno = EACCES;
5778         }
5779
5780         return result;
5781 }
5782
5783 /****************************************************************************
5784  Check the time parameters allow a print operation.
5785 *****************************************************************************/
5786
5787 bool print_time_access_check(const char *servicename)
5788 {
5789         NT_PRINTER_INFO_LEVEL *printer = NULL;
5790         bool ok = False;
5791         time_t now = time(NULL);
5792         struct tm *t;
5793         uint32 mins;
5794
5795         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5796                 return False;
5797
5798         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5799                 ok = True;
5800
5801         t = gmtime(&now);
5802         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5803
5804         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5805                 ok = True;
5806
5807         free_a_printer(&printer, 2);
5808
5809         if (!ok)
5810                 errno = EACCES;
5811
5812         return ok;
5813 }
5814
5815 /****************************************************************************
5816  Fill in the servername sent in the _spoolss_open_printer_ex() call
5817 ****************************************************************************/
5818
5819 char* get_server_name( Printer_entry *printer )
5820 {
5821         return printer->servername;
5822 }
5823
5824