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