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