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