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