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