r5029: after talking to Rob, ensure that we set the NETIOSNAME.domainname
[gd/samba/.git] / source / 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         fstring dnssuffix;
2599         char *allocated_string = NULL;
2600         const char *ascii_str;
2601         int i;
2602
2603         if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2604                 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2605         ctr = &info2->data.keys[i].values;
2606
2607         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2608         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2609
2610         /* we make the assumption that the netbios name is the same 
2611            as the DNS name sinc ethe former will be what we used to 
2612            join the domain */
2613
2614         if ( get_mydnsdomname( dnssuffix ) )
2615                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2616         else
2617                 fstrcpy( longname, global_myname() );
2618                 
2619         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2620
2621         asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2622         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2623         SAFE_FREE(allocated_string);
2624
2625         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2626         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2627         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2628         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2629         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2630         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2631         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2632         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2633         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2634
2635         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2636                           (info2->attributes & 
2637                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2638
2639         switch (info2->attributes & 0x3) {
2640         case 0:
2641                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2642                 break;
2643         case 1:
2644                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2645                 break;
2646         case 2:
2647                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2648                 break;
2649         default:
2650                 ascii_str = "unknown";
2651         }
2652         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2653
2654         return True;
2655 }
2656
2657 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, 
2658                                struct uuid guid)
2659 {
2660         int i;
2661         REGVAL_CTR *ctr=NULL;
2662
2663         /* find the DsSpooler key */
2664         if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2665                 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2666         ctr = &info2->data.keys[i].values;
2667
2668         regval_ctr_delvalue(ctr, "objectGUID");
2669         regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY, 
2670                             (char *) &guid, sizeof(struct uuid));       
2671 }
2672
2673 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2674                                      NT_PRINTER_INFO_LEVEL *printer)
2675 {
2676         ADS_STATUS ads_rc;
2677         void *res;
2678         char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2679         char *srv_dn_utf8, **srv_cn_utf8;
2680         TALLOC_CTX *ctx;
2681         ADS_MODLIST mods;
2682         const char *attrs[] = {"objectGUID", NULL};
2683         struct uuid guid;
2684         WERROR win_rc = WERR_OK;
2685
2686         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2687
2688         /* figure out where to publish */
2689         ads_find_machine_acct(ads, &res, global_myname());
2690
2691         /* We use ldap_get_dn here as we need the answer
2692          * in utf8 to call ldap_explode_dn(). JRA. */
2693
2694         srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2695         if (!srv_dn_utf8) {
2696                 ads_destroy(&ads);
2697                 return WERR_SERVER_UNAVAILABLE;
2698         }
2699         ads_msgfree(ads, res);
2700         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2701         if (!srv_cn_utf8) {
2702                 ldap_memfree(srv_dn_utf8);
2703                 ads_destroy(&ads);
2704                 return WERR_SERVER_UNAVAILABLE;
2705         }
2706         /* Now convert to CH_UNIX. */
2707         if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2708                 ldap_memfree(srv_dn_utf8);
2709                 ldap_memfree(srv_cn_utf8);
2710                 ads_destroy(&ads);
2711                 return WERR_SERVER_UNAVAILABLE;
2712         }
2713         if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2714                 ldap_memfree(srv_dn_utf8);
2715                 ldap_memfree(srv_cn_utf8);
2716                 ads_destroy(&ads);
2717                 SAFE_FREE(srv_dn);
2718                 return WERR_SERVER_UNAVAILABLE;
2719         }
2720
2721         ldap_memfree(srv_dn_utf8);
2722         ldap_memfree(srv_cn_utf8);
2723
2724         asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0, 
2725                  printer->info_2->sharename, srv_dn);
2726
2727         SAFE_FREE(srv_dn);
2728         SAFE_FREE(srv_cn_0);
2729
2730         /* build the ads mods */
2731         ctx = talloc_init("nt_printer_publish_ads");
2732         mods = ads_init_mods(ctx);
2733
2734         get_local_printer_publishing_data(ctx, &mods, 
2735                                           &printer->info_2->data);
2736         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, 
2737                     printer->info_2->sharename);
2738
2739         /* publish it */
2740         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2741         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
2742                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2743
2744         if (!ADS_ERR_OK(ads_rc))
2745                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2746         
2747         talloc_destroy(ctx);
2748
2749         /* retreive the guid and store it locally */
2750         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2751                 ZERO_STRUCT(guid);
2752                 ads_pull_guid(ads, res, &guid);
2753                 ads_msgfree(ads, res);
2754                 store_printer_guid(printer->info_2, guid);
2755                 win_rc = mod_a_printer(printer, 2);
2756         } 
2757
2758         SAFE_FREE(prt_dn);
2759         return win_rc;
2760 }
2761
2762 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2763                                        NT_PRINTER_INFO_LEVEL *printer)
2764 {
2765         ADS_STATUS ads_rc;
2766         void *res;
2767         char *prt_dn = NULL;
2768
2769         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2770
2771         /* remove the printer from the directory */
2772         ads_rc = ads_find_printer_on_server(ads, &res, 
2773                             printer->info_2->sharename, global_myname());
2774
2775         if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2776                 prt_dn = ads_get_dn(ads, res);
2777                 ads_rc = ads_del_dn(ads, prt_dn);
2778                 ads_memfree(ads, prt_dn);
2779         }
2780
2781         ads_msgfree(ads, res);
2782         return WERR_OK;
2783 }
2784
2785 /****************************************************************************
2786  * Publish a printer in the directory
2787  *
2788  * @param snum describing printer service
2789  * @return WERROR indicating status of publishing
2790  ***************************************************************************/
2791
2792 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2793 {
2794         ADS_STATUS ads_rc;
2795         ADS_STRUCT *ads = NULL;
2796         NT_PRINTER_INFO_LEVEL *printer = NULL;
2797         WERROR win_rc;
2798
2799         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2800         if (!W_ERROR_IS_OK(win_rc))
2801                 goto done;
2802
2803         switch (action) {
2804         case SPOOL_DS_PUBLISH:
2805         case SPOOL_DS_UPDATE:
2806                 /* set the DsSpooler info and attributes */
2807                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
2808                         win_rc = WERR_NOMEM;
2809                         goto done;
2810                 }
2811
2812                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2813                 break;
2814         case SPOOL_DS_UNPUBLISH:
2815                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2816                 break;
2817         default:
2818                 win_rc = WERR_NOT_SUPPORTED;
2819                 goto done;
2820         }
2821
2822         win_rc = mod_a_printer(printer, 2);
2823         if (!W_ERROR_IS_OK(win_rc)) {
2824                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2825                 goto done;
2826         }
2827
2828         ads = ads_init(NULL, NULL, NULL);
2829         if (!ads) {
2830                 DEBUG(3, ("ads_init() failed\n"));
2831                 win_rc = WERR_SERVER_UNAVAILABLE;
2832                 goto done;
2833         }
2834         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2835         SAFE_FREE(ads->auth.password);
2836         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2837                 NULL, NULL);
2838
2839         /* ads_connect() will find the DC for us */                                         
2840         ads_rc = ads_connect(ads);
2841         if (!ADS_ERR_OK(ads_rc)) {
2842                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2843                 win_rc = WERR_ACCESS_DENIED;
2844                 goto done;
2845         }
2846
2847         switch (action) {
2848         case SPOOL_DS_PUBLISH:
2849         case SPOOL_DS_UPDATE:
2850                 win_rc = nt_printer_publish_ads(ads, printer);
2851                 break;
2852         case SPOOL_DS_UNPUBLISH:
2853                 win_rc = nt_printer_unpublish_ads(ads, printer);
2854                 break;
2855         }
2856
2857 done:
2858         free_a_printer(&printer, 2);
2859         ads_destroy(&ads);
2860         return win_rc;
2861 }
2862
2863 WERROR check_published_printers(void)
2864 {
2865         ADS_STATUS ads_rc;
2866         ADS_STRUCT *ads = NULL;
2867         int snum;
2868         int n_services = lp_numservices();
2869         NT_PRINTER_INFO_LEVEL *printer = NULL;
2870
2871         ads = ads_init(NULL, NULL, NULL);
2872         if (!ads) {
2873                 DEBUG(3, ("ads_init() failed\n"));
2874                 return WERR_SERVER_UNAVAILABLE;
2875         }
2876         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2877         SAFE_FREE(ads->auth.password);
2878         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2879                 NULL, NULL);
2880
2881         /* ads_connect() will find the DC for us */                                         
2882         ads_rc = ads_connect(ads);
2883         if (!ADS_ERR_OK(ads_rc)) {
2884                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2885                 ads_destroy(&ads);
2886                 return WERR_ACCESS_DENIED;
2887         }
2888
2889         for (snum = 0; snum < n_services; snum++) {
2890                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
2891                         continue;
2892
2893                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
2894                                                 lp_servicename(snum))) &&
2895                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2896                         nt_printer_publish_ads(ads, printer);
2897
2898                 free_a_printer(&printer, 2);
2899         }
2900
2901         ads_destroy(&ads);
2902         return WERR_OK;
2903 }
2904
2905 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
2906                           struct uuid *guid)
2907 {
2908         NT_PRINTER_INFO_LEVEL *printer = NULL;
2909         REGVAL_CTR *ctr;
2910         REGISTRY_VALUE *guid_val;
2911         WERROR win_rc;
2912         int i;
2913
2914         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2915
2916         if (!W_ERROR_IS_OK(win_rc) ||
2917             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
2918             ((i = lookup_printerkey(&printer->info_2->data, 
2919                                     SPOOL_DSSPOOLER_KEY)) < 0) ||
2920             !(ctr = &printer->info_2->data.keys[i].values) ||
2921             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2922                 free_a_printer(&printer, 2);
2923                 return False;
2924         }
2925
2926         /* fetching printer guids really ought to be a separate function.. */
2927         if (guid && regval_size(guid_val) == sizeof(struct uuid))
2928                 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
2929
2930         free_a_printer(&printer, 2);
2931         return True;
2932 }
2933 #else
2934 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2935 {
2936         return WERR_OK;
2937 }
2938
2939 WERROR check_published_printers(void)
2940 {
2941         return WERR_OK;
2942 }
2943
2944 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
2945                           struct uuid *guid)
2946 {
2947         return False;
2948 }
2949 #endif /* HAVE_ADS */
2950
2951 /****************************************************************************
2952  ***************************************************************************/
2953  
2954 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2955 {
2956         NT_PRINTER_DATA *data;
2957         int             i;
2958         int             removed_keys = 0;
2959         int             empty_slot;
2960         
2961         data = &p2->data;
2962         empty_slot = data->num_keys;
2963
2964         if ( !key )
2965                 return WERR_INVALID_PARAM;
2966         
2967         /* remove all keys */
2968
2969         if ( !strlen(key) ) {
2970                 for ( i=0; i<data->num_keys; i++ ) {
2971                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2972                                 data->keys[i].name));
2973                 
2974                         SAFE_FREE( data->keys[i].name );
2975                         regval_ctr_destroy( &data->keys[i].values );
2976                 }
2977         
2978                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2979                         p2->printername ));
2980         
2981                 SAFE_FREE( data->keys );
2982                 ZERO_STRUCTP( data );
2983
2984                 return WERR_OK;
2985         }
2986
2987         /* remove a specific key (and all subkeys) */
2988         
2989         for ( i=0; i<data->num_keys; i++ ) {
2990                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2991                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2992                                 data->keys[i].name));
2993                 
2994                         SAFE_FREE( data->keys[i].name );
2995                         regval_ctr_destroy( &data->keys[i].values );
2996                 
2997                         /* mark the slot as empty */
2998
2999                         ZERO_STRUCTP( &data->keys[i] );
3000                 }
3001         }
3002
3003         /* find the first empty slot */
3004
3005         for ( i=0; i<data->num_keys; i++ ) {
3006                 if ( !data->keys[i].name ) {
3007                         empty_slot = i;
3008                         removed_keys++;
3009                         break;
3010                 }
3011         }
3012
3013         if ( i == data->num_keys )
3014                 /* nothing was removed */
3015                 return WERR_INVALID_PARAM;
3016
3017         /* move everything down */
3018         
3019         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3020                 if ( data->keys[i].name ) {
3021                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
3022                         ZERO_STRUCTP( &data->keys[i] );
3023                         empty_slot++;
3024                         removed_keys++;
3025                 }
3026         }
3027
3028         /* update count */
3029                 
3030         data->num_keys -= removed_keys;
3031
3032         /* sanity check to see if anything is left */
3033
3034         if ( !data->num_keys ) {
3035                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3036
3037                 SAFE_FREE( data->keys );
3038                 ZERO_STRUCTP( data );
3039         }
3040
3041         return WERR_OK;
3042 }
3043
3044 /****************************************************************************
3045  ***************************************************************************/
3046  
3047 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3048 {
3049         WERROR          result = WERR_OK;
3050         int             key_index;
3051         
3052         /* we must have names on non-zero length */
3053         
3054         if ( !key || !*key|| !value || !*value )
3055                 return WERR_INVALID_NAME;
3056                 
3057         /* find the printer key first */
3058
3059         key_index = lookup_printerkey( &p2->data, key );
3060         if ( key_index == -1 )
3061                 return WERR_OK;
3062         
3063         /* make sure the value exists so we can return the correct error code */
3064         
3065         if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
3066                 return WERR_BADFILE;
3067                 
3068         regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
3069         
3070         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3071                 key, value ));
3072         
3073         return result;
3074 }
3075
3076 /****************************************************************************
3077  ***************************************************************************/
3078  
3079 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
3080                            uint32 type, uint8 *data, int real_len )
3081 {
3082         WERROR          result = WERR_OK;
3083         int             key_index;
3084
3085         /* we must have names on non-zero length */
3086         
3087         if ( !key || !*key|| !value || !*value )
3088                 return WERR_INVALID_NAME;
3089                 
3090         /* find the printer key first */
3091         
3092         key_index = lookup_printerkey( &p2->data, key );
3093         if ( key_index == -1 )
3094                 key_index = add_new_printer_key( &p2->data, key );
3095                 
3096         if ( key_index == -1 )
3097                 return WERR_NOMEM;
3098         
3099         regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3100                 type, (const char *)data, real_len );
3101         
3102         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3103                 key, value, type, real_len  ));
3104         
3105         return result;
3106 }
3107
3108 /****************************************************************************
3109  ***************************************************************************/
3110  
3111 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3112 {
3113         int             key_index;
3114
3115         if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3116                 return NULL;
3117
3118         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3119                 key, value ));
3120
3121         return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3122 }
3123
3124 /****************************************************************************
3125  Unpack a list of registry values frem the TDB
3126  ***************************************************************************/
3127  
3128 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3129 {
3130         int             len = 0;
3131         uint32          type;
3132         pstring         string, valuename, keyname;
3133         char            *str;
3134         int             size;
3135         uint8           *data_p;
3136         REGISTRY_VALUE  *regval_p;
3137         int             key_index;
3138         
3139         /* add the "PrinterDriverData" key first for performance reasons */
3140         
3141         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3142
3143         /* loop and unpack the rest of the registry values */
3144         
3145         while ( True ) {
3146         
3147                 /* check to see if there are any more registry values */
3148                 
3149                 regval_p = NULL;
3150                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
3151                 if ( !regval_p ) 
3152                         break;
3153
3154                 /* unpack the next regval */
3155                 
3156                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3157                                   string,
3158                                   &type,
3159                                   &size,
3160                                   &data_p);
3161         
3162                 /*
3163                  * break of the keyname from the value name.  
3164                  * Valuenames can have embedded '\'s so be careful.
3165                  * only support one level of keys.  See the 
3166                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3167                  * -- jerry
3168                  */     
3169                  
3170                 str = strchr_m( string, '\\');
3171                 
3172                 /* Put in "PrinterDriverData" is no key specified */
3173                 
3174                 if ( !str ) {
3175                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3176                         pstrcpy( valuename, string );
3177                 }
3178                 else {
3179                         *str = '\0';
3180                         pstrcpy( keyname, string );
3181                         pstrcpy( valuename, str+1 );
3182                 }
3183                         
3184                 /* see if we need a new key */
3185                 
3186                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3187                         key_index = add_new_printer_key( printer_data, keyname );
3188                         
3189                 if ( key_index == -1 ) {
3190                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3191                                 keyname));
3192                         break;
3193                 }
3194                 
3195                 /* add the new value */
3196                 
3197                 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3198
3199                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3200
3201                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3202         }
3203
3204         return len;
3205 }
3206
3207 /****************************************************************************
3208  ***************************************************************************/
3209
3210 static void map_to_os2_driver(fstring drivername)
3211 {
3212         static BOOL initialised=False;
3213         static fstring last_from,last_to;
3214         char *mapfile = lp_os2_driver_map();
3215         char **lines = NULL;
3216         int numlines = 0;
3217         int i;
3218
3219         if (!strlen(drivername))
3220                 return;
3221
3222         if (!*mapfile)
3223                 return;
3224
3225         if (!initialised) {
3226                 *last_from = *last_to = 0;
3227                 initialised = True;
3228         }
3229
3230         if (strequal(drivername,last_from)) {
3231                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3232                 fstrcpy(drivername,last_to);
3233                 return;
3234         }
3235
3236         lines = file_lines_load(mapfile, &numlines);
3237         if (numlines == 0) {
3238                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3239                 return;
3240         }
3241
3242         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3243
3244         for( i = 0; i < numlines; i++) {
3245                 char *nt_name = lines[i];
3246                 char *os2_name = strchr(nt_name,'=');
3247
3248                 if (!os2_name)
3249                         continue;
3250
3251                 *os2_name++ = 0;
3252
3253                 while (isspace(*nt_name))
3254                         nt_name++;
3255
3256                 if (!*nt_name || strchr("#;",*nt_name))
3257                         continue;
3258
3259                 {
3260                         int l = strlen(nt_name);
3261                         while (l && isspace(nt_name[l-1])) {
3262                                 nt_name[l-1] = 0;
3263                                 l--;
3264                         }
3265                 }
3266
3267                 while (isspace(*os2_name))
3268                         os2_name++;
3269
3270                 {
3271                         int l = strlen(os2_name);
3272                         while (l && isspace(os2_name[l-1])) {
3273                                 os2_name[l-1] = 0;
3274                                 l--;
3275                         }
3276                 }
3277
3278                 if (strequal(nt_name,drivername)) {
3279                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3280                         fstrcpy(last_from,drivername);
3281                         fstrcpy(last_to,os2_name);
3282                         fstrcpy(drivername,os2_name);
3283                         file_lines_free(lines);
3284                         return;
3285                 }
3286         }
3287
3288         file_lines_free(lines);
3289 }
3290
3291 /****************************************************************************
3292  Get a default printer info 2 struct.
3293 ****************************************************************************/
3294 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char* sharename)
3295 {
3296         int snum;
3297         NT_PRINTER_INFO_LEVEL_2 info;
3298
3299         ZERO_STRUCT(info);
3300
3301         snum = lp_servicenumber(sharename);
3302
3303         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3304         slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
3305                 servername, sharename);
3306         fstrcpy(info.sharename, sharename);
3307         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3308
3309         /* by setting the driver name to an empty string, a local NT admin
3310            can now run the **local** APW to install a local printer driver
3311            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3312            installed on the Samba server for NT clients --jerry */
3313 #if 0   /* JERRY --do not uncomment-- */
3314         if (!*info.drivername)
3315                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3316 #endif
3317
3318
3319         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3320
3321         pstrcpy(info.comment, "");
3322         fstrcpy(info.printprocessor, "winprint");
3323         fstrcpy(info.datatype, "RAW");
3324
3325         info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3326
3327         info.starttime = 0; /* Minutes since 12:00am GMT */
3328         info.untiltime = 0; /* Minutes since 12:00am GMT */
3329         info.priority = 1;
3330         info.default_priority = 1;
3331         info.setuptime = (uint32)time(NULL);
3332
3333         /*
3334          * I changed this as I think it is better to have a generic
3335          * DEVMODE than to crash Win2k explorer.exe   --jerry
3336          * See the HP Deskjet 990c Win2k drivers for an example.
3337          *
3338          * However the default devmode appears to cause problems
3339          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3340          * the "default devmode" parameter   --jerry 22/01/2002
3341          */
3342
3343         if (lp_default_devmode(snum)) {
3344                 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3345                         goto fail;
3346         }
3347         else {
3348                 info.devmode = NULL;
3349         }
3350
3351         /* This will get the current RPC talloc context, but we should be
3352            passing this as a parameter... fixme... JRA ! */
3353
3354         if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3355                 goto fail;
3356
3357         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3358         if (! *info_ptr) {
3359                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3360                 goto fail;
3361         }
3362
3363         return WERR_OK;
3364
3365   fail:
3366         if (info.devmode)
3367                 free_nt_devicemode(&info.devmode);
3368         return WERR_ACCESS_DENIED;
3369 }
3370
3371 /****************************************************************************
3372 ****************************************************************************/
3373 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename)
3374 {
3375         pstring key;
3376         NT_PRINTER_INFO_LEVEL_2 info;
3377         int len = 0;
3378         int snum = lp_servicenumber(sharename);
3379         TDB_DATA kbuf, dbuf;
3380         fstring printername;
3381         char adevice[MAXDEVICENAME];
3382                 
3383         ZERO_STRUCT(info);
3384
3385         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3386
3387         kbuf.dptr = key;
3388         kbuf.dsize = strlen(key)+1;
3389
3390         dbuf = tdb_fetch(tdb_printers, kbuf);
3391         if (!dbuf.dptr)
3392                 return get_a_printer_2_default(info_ptr, servername, sharename);
3393
3394         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3395                         &info.attributes,
3396                         &info.priority,
3397                         &info.default_priority,
3398                         &info.starttime,
3399                         &info.untiltime,
3400                         &info.status,
3401                         &info.cjobs,
3402                         &info.averageppm,
3403                         &info.changeid,
3404                         &info.c_setprinter,
3405                         &info.setuptime,
3406                         info.servername,
3407                         info.printername,
3408                         info.sharename,
3409                         info.portname,
3410                         info.drivername,
3411                         info.comment,
3412                         info.location,
3413                         info.sepfile,
3414                         info.printprocessor,
3415                         info.datatype,
3416                         info.parameters);
3417
3418         /* Samba has to have shared raw drivers. */
3419         info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3420         info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3421
3422         /* Restore the stripped strings. */
3423         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3424
3425         if ( lp_force_printername(snum) )
3426                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3427         else 
3428                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
3429
3430         fstrcpy(info.printername, printername);
3431
3432         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3433
3434         /*
3435          * Some client drivers freak out if there is a NULL devmode
3436          * (probably the driver is not checking before accessing 
3437          * the devmode pointer)   --jerry
3438          *
3439          * See comments in get_a_printer_2_default()
3440          */
3441
3442         if (lp_default_devmode(snum) && !info.devmode) {
3443                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3444                         printername));
3445                 info.devmode = construct_nt_devicemode(printername);
3446         }
3447
3448         slprintf( adevice, sizeof(adevice), "%s", info.printername );
3449         if (info.devmode) {
3450                 fstrcpy(info.devmode->devicename, adevice);     
3451         }
3452
3453         len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3454
3455         /* This will get the current RPC talloc context, but we should be
3456            passing this as a parameter... fixme... JRA ! */
3457
3458         nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3459
3460         /* Fix for OS/2 drivers. */
3461
3462         if (get_remote_arch() == RA_OS2)
3463                 map_to_os2_driver(info.drivername);
3464
3465         SAFE_FREE(dbuf.dptr);
3466         *info_ptr=memdup(&info, sizeof(info));
3467
3468         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3469                  sharename, info.printername, info.drivername));
3470
3471         return WERR_OK; 
3472 }
3473
3474 /****************************************************************************
3475  Debugging function, dump at level 6 the struct in the logs.
3476 ****************************************************************************/
3477 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3478 {
3479         uint32 result;
3480         NT_PRINTER_INFO_LEVEL_2 *info2;
3481         
3482         DEBUG(106,("Dumping printer at level [%d]\n", level));
3483         
3484         switch (level) {
3485                 case 2:
3486                 {
3487                         if (printer->info_2 == NULL)
3488                                 result=5;
3489                         else
3490                         {
3491                                 info2=printer->info_2;
3492                         
3493                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3494                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3495                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3496                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3497                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3498                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3499                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3500                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3501                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3502                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3503                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3504
3505                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3506                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3507                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3508                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3509                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3510                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3511                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3512                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3513                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3514                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3515                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3516                                 result=0;
3517                         }
3518                         break;
3519                 }
3520                 default:
3521                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3522                         result=1;
3523                         break;
3524         }
3525         
3526         return result;
3527 }
3528
3529 /****************************************************************************
3530  Update the changeid time.
3531  This is SO NASTY as some drivers need this to change, others need it
3532  static. This value will change every second, and I must hope that this
3533  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3534  UTAH ! JRA.
3535 ****************************************************************************/
3536
3537 static uint32 rev_changeid(void)
3538 {
3539         struct timeval tv;
3540
3541         get_process_uptime(&tv);
3542
3543 #if 1   /* JERRY */
3544         /* Return changeid as msec since spooler restart */
3545         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3546 #else
3547         /*
3548          * This setting seems to work well but is too untested
3549          * to replace the above calculation.  Left in for experiementation
3550          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3551          */
3552         return tv.tv_sec * 10 + tv.tv_usec / 100000;
3553 #endif
3554 }
3555
3556 /********************************************************************
3557  Send a message to all smbds about the printer that just changed
3558  ********************************************************************/
3559  
3560 static BOOL send_printer_mod_msg( char* printername )
3561 {
3562         int len = strlen(printername);
3563         
3564         if (!len)
3565                 return False;
3566
3567         DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3568                 printername));
3569                 
3570         /* spam everyone that we just changed this printer */
3571         
3572         message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3573
3574         return True;
3575 }
3576
3577 /*
3578  * The function below are the high level ones.
3579  * only those ones must be called from the spoolss code.
3580  * JFM.
3581  */
3582
3583 /****************************************************************************
3584  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3585 ****************************************************************************/
3586
3587 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3588 {
3589         WERROR result;
3590         
3591         dump_a_printer(printer, level); 
3592         
3593         /* 
3594          * invalidate cache for all open handles to this printer.
3595          * cache for a given handle will be updated on the next 
3596          * get_a_printer() 
3597          */
3598          
3599         invalidate_printer_hnd_cache( printer->info_2->sharename );
3600         send_printer_mod_msg( printer->info_2->sharename );
3601         
3602         switch (level) {
3603                 case 2:
3604                 {
3605                         /*
3606                          * Update the changestamp.  Emperical tests show that the
3607                          * ChangeID is always updated,but c_setprinter is  
3608                          *  global spooler variable (not per printer).
3609                          */
3610
3611                         /* ChangeID **must** be increasing over the lifetime
3612                            of client's spoolss service in order for the
3613                            client's cache to show updates */
3614
3615                         printer->info_2->changeid = rev_changeid();
3616
3617                         /*
3618                          * Because one day someone will ask:
3619                          * NT->NT       An admin connection to a remote
3620                          *              printer show changes imeediately in
3621                          *              the properities dialog
3622                          *      
3623                          *              A non-admin connection will only show the
3624                          *              changes after viewing the properites page
3625                          *              2 times.  Seems to be related to a
3626                          *              race condition in the client between the spooler
3627                          *              updating the local cache and the Explorer.exe GUI
3628                          *              actually displaying the properties.
3629                          *
3630                          *              This is fixed in Win2k.  admin/non-admin
3631                          *              connections both display changes immediately.
3632                          *
3633                          * 14/12/01     --jerry
3634                          */
3635
3636                         result=update_a_printer_2(printer->info_2);
3637                         
3638                         break;
3639                 }
3640                 default:
3641                         result=WERR_UNKNOWN_LEVEL;
3642                         break;
3643         }
3644         
3645         return result;
3646 }
3647
3648 /****************************************************************************
3649  Initialize printer devmode & data with previously saved driver init values.
3650 ****************************************************************************/
3651
3652 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3653 {
3654         int                     len = 0;
3655         pstring                 key;
3656         TDB_DATA                kbuf, dbuf;
3657         NT_PRINTER_INFO_LEVEL_2 info;
3658
3659
3660         ZERO_STRUCT(info);
3661
3662         /*
3663          * Delete any printer data 'values' already set. When called for driver
3664          * replace, there will generally be some, but during an add printer, there
3665          * should not be any (if there are delete them).
3666          */
3667          
3668         delete_all_printer_data( info_ptr, "" );
3669         
3670         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3671
3672         kbuf.dptr = key;
3673         kbuf.dsize = strlen(key)+1;
3674
3675         dbuf = tdb_fetch(tdb_drivers, kbuf);
3676         if (!dbuf.dptr) {
3677                 /*
3678                  * When changing to a driver that has no init info in the tdb, remove
3679                  * the previous drivers init info and leave the new on blank.
3680                  */
3681                 free_nt_devicemode(&info_ptr->devmode);
3682                 return False;
3683         }
3684         
3685         /*
3686          * Get the saved DEVMODE..
3687          */
3688          
3689         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3690
3691         /*
3692          * The saved DEVMODE contains the devicename from the printer used during
3693          * the initialization save. Change it to reflect the new printer.
3694          */
3695          
3696         if ( info.devmode ) {
3697                 ZERO_STRUCT(info.devmode->devicename);
3698                 fstrcpy(info.devmode->devicename, info_ptr->printername);
3699         }
3700
3701         /*
3702          * NT/2k does not change out the entire DeviceMode of a printer
3703          * when changing the driver.  Only the driverextra, private, & 
3704          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3705          *
3706          * Later examination revealed that Windows NT/2k does reset the
3707          * the printer's device mode, bit **only** when you change a 
3708          * property of the device mode such as the page orientation.
3709          * --jerry
3710          */
3711
3712
3713         /* Bind the saved DEVMODE to the new the printer */
3714          
3715         free_nt_devicemode(&info_ptr->devmode);
3716         info_ptr->devmode = info.devmode;
3717
3718         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3719                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3720
3721         /* Add the printer data 'values' to the new printer */
3722          
3723         len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3724         
3725
3726         SAFE_FREE(dbuf.dptr);
3727
3728         return True;    
3729 }
3730
3731 /****************************************************************************
3732  Initialize printer devmode & data with previously saved driver init values.
3733  When a printer is created using AddPrinter, the drivername bound to the
3734  printer is used to lookup previously saved driver initialization info, which
3735  is bound to the new printer.
3736 ****************************************************************************/
3737
3738 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3739 {
3740         BOOL result = False;
3741         
3742         switch (level) {
3743                 case 2:
3744                         result = set_driver_init_2(printer->info_2);
3745                         break;
3746                         
3747                 default:
3748                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
3749                                 level));
3750                         break;
3751         }
3752         
3753         return result;
3754 }
3755
3756 /****************************************************************************
3757  Delete driver init data stored for a specified driver
3758 ****************************************************************************/
3759
3760 BOOL del_driver_init(char *drivername)
3761 {
3762         pstring key;
3763         TDB_DATA kbuf;
3764
3765         if (!drivername || !*drivername) {
3766                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3767                 return False;
3768         }
3769
3770         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3771
3772         kbuf.dptr = key;
3773         kbuf.dsize = strlen(key)+1;
3774
3775         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3776
3777         return (tdb_delete(tdb_drivers, kbuf) == 0);
3778 }
3779
3780 /****************************************************************************
3781  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
3782  in the tdb. Note: this is different from the driver entry and the printer
3783  entry. There should be a single driver init entry for each driver regardless
3784  of whether it was installed from NT or 2K. Technically, they should be
3785  different, but they work out to the same struct.
3786 ****************************************************************************/
3787
3788 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3789 {
3790         pstring key;
3791         char *buf;
3792         int buflen, len, ret;
3793         TDB_DATA kbuf, dbuf;
3794
3795         buf = NULL;
3796         buflen = 0;
3797
3798  again: 
3799         len = 0;
3800         len += pack_devicemode(info->devmode, buf+len, buflen-len);
3801
3802         len += pack_values( &info->data, buf+len, buflen-len );
3803
3804         if (buflen < len) {
3805                 char *tb;
3806
3807                 tb = (char *)SMB_REALLOC(buf, len);
3808                 if (!tb) {
3809                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3810                         ret = -1;
3811                         goto done;
3812                 }
3813                 else
3814                         buf = tb;
3815                 buflen = len;
3816                 goto again;
3817         }
3818
3819         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3820
3821         kbuf.dptr = key;
3822         kbuf.dsize = strlen(key)+1;
3823         dbuf.dptr = buf;
3824         dbuf.dsize = len;
3825
3826         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3827
3828 done:
3829         if (ret == -1)
3830                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3831
3832         SAFE_FREE(buf);
3833
3834         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3835                  info->sharename, info->drivername));
3836
3837         return ret;
3838 }
3839
3840 /****************************************************************************
3841  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3842 ****************************************************************************/
3843
3844 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3845 {
3846         uint32 result;
3847         
3848         dump_a_printer(printer, level); 
3849         
3850         switch (level) {
3851                 case 2:
3852                         result = update_driver_init_2(printer->info_2);
3853                         break;
3854                 default:
3855                         result = 1;
3856                         break;
3857         }
3858         
3859         return result;
3860 }
3861
3862 /****************************************************************************
3863  Convert the printer data value, a REG_BINARY array, into an initialization 
3864  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3865  got to keep the endians happy :).
3866 ****************************************************************************/
3867
3868 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3869 {
3870         BOOL       result = False;
3871         prs_struct ps;
3872         DEVICEMODE devmode;
3873
3874         ZERO_STRUCT(devmode);
3875
3876         prs_init(&ps, 0, ctx, UNMARSHALL);
3877         ps.data_p      = (char *)data;
3878         ps.buffer_size = data_len;
3879
3880         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3881                 result = convert_devicemode("", &devmode, &nt_devmode);
3882         else
3883                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3884
3885         return result;
3886 }
3887
3888 /****************************************************************************
3889  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3890
3891  1. Use the driver's config DLL to this UNC printername and:
3892     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3893     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3894  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3895
3896  The last step triggers saving the "driver initialization" information for
3897  this printer into the tdb. Later, new printers that use this driver will
3898  have this initialization information bound to them. This simulates the
3899  driver initialization, as if it had run on the Samba server (as it would
3900  have done on NT).
3901
3902  The Win32 client side code requirement sucks! But until we can run arbitrary
3903  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3904  
3905  It would have been easier to use SetPrinter because all the UNMARSHALLING of
3906  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3907  about it and you will realize why.  JRR 010720
3908 ****************************************************************************/
3909
3910 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3911 {
3912         WERROR        status       = WERR_OK;
3913         TALLOC_CTX    *ctx         = NULL;
3914         NT_DEVICEMODE *nt_devmode  = NULL;
3915         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3916         
3917         /*
3918          * When the DEVMODE is already set on the printer, don't try to unpack it.
3919          */
3920         DEBUG(8,("save_driver_init_2: Enter...\n"));
3921         
3922         if ( !printer->info_2->devmode && data_len ) {
3923                 /*
3924                  * Set devmode on printer info, so entire printer initialization can be
3925                  * saved to tdb.
3926                  */
3927
3928                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3929                         return WERR_NOMEM;
3930
3931                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
3932                         status = WERR_NOMEM;
3933                         goto done;
3934                 }
3935         
3936                 ZERO_STRUCTP(nt_devmode);
3937
3938                 /*
3939                  * The DEVMODE is held in the 'data' component of the param in raw binary.
3940                  * Convert it to to a devmode structure
3941                  */
3942                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3943                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3944                         status = WERR_INVALID_PARAM;
3945                         goto done;
3946                 }
3947
3948                 printer->info_2->devmode = nt_devmode;
3949         }
3950
3951         /*
3952          * Pack up and add (or update) the DEVMODE and any current printer data to
3953          * a 'driver init' element in the tdb
3954          * 
3955          */
3956
3957         if ( update_driver_init(printer, 2) != 0 ) {
3958                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3959                 status = WERR_NOMEM;
3960                 goto done;
3961         }
3962         
3963         /*
3964          * If driver initialization info was successfully saved, set the current 
3965          * printer to match it. This allows initialization of the current printer 
3966          * as well as the driver.
3967          */
3968         status = mod_a_printer(printer, 2);
3969         if (!W_ERROR_IS_OK(status)) {
3970                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3971                                   printer->info_2->printername));
3972         }
3973         
3974   done:
3975         talloc_destroy(ctx);
3976         free_nt_devicemode( &nt_devmode );
3977         
3978         printer->info_2->devmode = tmp_devmode;
3979
3980         return status;
3981 }
3982
3983 /****************************************************************************
3984  Update the driver init info (DEVMODE and specifics) for a printer
3985 ****************************************************************************/
3986
3987 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3988 {
3989         WERROR status = WERR_OK;
3990         
3991         switch (level) {
3992                 case 2:
3993                         status = save_driver_init_2( printer, data, data_len );
3994                         break;
3995                 default:
3996                         status = WERR_UNKNOWN_LEVEL;
3997                         break;
3998         }
3999         
4000         return status;
4001 }
4002
4003 /****************************************************************************
4004  Deep copy a NT_PRINTER_DATA
4005 ****************************************************************************/
4006
4007 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
4008 {
4009         int i, j, num_vals, new_key_index;
4010         REGVAL_CTR *src_key, *dst_key;
4011         
4012         if ( !dst || !src )
4013                 return NT_STATUS_NO_MEMORY;
4014         
4015         for ( i=0; i<src->num_keys; i++ ) {
4016                            
4017                 /* create a new instance of the printerkey in the destination 
4018                    printer_data object */
4019                    
4020                 new_key_index = add_new_printer_key( dst, src->keys[i].name );
4021                 dst_key = &dst->keys[new_key_index].values;
4022
4023                 src_key = &src->keys[i].values;
4024                 num_vals = regval_ctr_numvals( src_key );
4025                 
4026                 /* dup the printer entire printer key */
4027                 
4028                 for ( j=0; j<num_vals; j++ ) {
4029                         regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
4030                 }
4031         }
4032                 
4033         return NT_STATUS_OK;
4034 }
4035
4036 /****************************************************************************
4037  Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4038  Caller must free.
4039 ****************************************************************************/
4040
4041 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
4042 {
4043         NT_PRINTER_INFO_LEVEL_2 *copy;
4044         
4045         if ( !printer )
4046                 return NULL;
4047         
4048         if ( !(copy = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2)) )
4049                 return NULL;
4050                 
4051         memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
4052         
4053         /* malloc()'d members copied here */
4054         
4055         copy->devmode = dup_nt_devicemode( printer->devmode );  
4056
4057         ZERO_STRUCT( copy->data );
4058         copy_printer_data( &copy->data, &printer->data );
4059         
4060         /* this is talloc()'d; very ugly that we have a structure that 
4061            is half malloc()'d and half talloc()'d but that is the way 
4062            that the PRINTER_INFO stuff is written right now.  --jerry  */
4063            
4064         copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
4065                 
4066         return copy;
4067 }
4068
4069 /****************************************************************************
4070  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4071
4072  Previously the code had a memory allocation problem because it always
4073  used the TALLOC_CTX from the Printer_entry*.   This context lasts 
4074  as a long as the original handle is open.  So if the client made a lot 
4075  of getprinter[data]() calls, the memory usage would climb.  Now we use
4076  a short lived TALLOC_CTX for printer_info_2 objects returned.  We 
4077  still use the Printer_entry->ctx for maintaining the cache copy though
4078  since that object must live as long as the handle by definition.  
4079                                                     --jerry
4080
4081 ****************************************************************************/
4082
4083 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
4084                         const char *sharename)
4085 {
4086         WERROR result;
4087         NT_PRINTER_INFO_LEVEL *printer = NULL;
4088         fstring servername;
4089         
4090         *pp_printer = NULL;
4091
4092         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4093
4094         switch (level) {
4095                 case 2:
4096                         if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
4097                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
4098                                 return WERR_NOMEM;
4099                         }
4100                         ZERO_STRUCTP(printer);
4101
4102                         if ( print_hnd ) 
4103                                 fstrcpy( servername, print_hnd->servername );
4104                         else {
4105                                 fstrcpy( servername, "%L" );
4106                                 standard_sub_basic( "", servername, sizeof(servername)-1 );
4107                         }
4108                         
4109                         /* 
4110                          * check for cache first.  A Printer handle cannot changed
4111                          * to another printer object so we only check that the printer 
4112                          * is actually for a printer and that the printer_info pointer 
4113                          * is valid
4114                          */
4115                         if ( print_hnd 
4116                                 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER) 
4117                                 && print_hnd->printer_info )
4118                         {
4119                                 /* get_talloc_ctx() works here because we need a short 
4120                                    lived talloc context */
4121
4122                                 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) ) 
4123                                 {
4124                                         DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4125                                         
4126                                         SAFE_FREE(printer);
4127                                         return WERR_NOMEM;
4128                                 }
4129                                 
4130                                 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4131                                 
4132                                 *pp_printer = printer;                          
4133                                 result = WERR_OK;
4134                                 
4135                                 break;
4136                         }
4137
4138                         /* no cache for this handle; see if we can match one from another handle.
4139                            Make sure to use a short lived talloc ctx */
4140
4141                         if ( print_hnd )
4142                                 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, servername, sharename);
4143                         
4144                         /* fail to disk if we don't have it with any open handle */
4145
4146                         if ( !print_hnd || !W_ERROR_IS_OK(result) )
4147                                 result = get_a_printer_2(&printer->info_2, servername, sharename );
4148                         
4149                         /* we have a new printer now.  Save it with this handle */
4150                         
4151                         if ( W_ERROR_IS_OK(result) ) {
4152                                 dump_a_printer(printer, level);
4153                                         
4154                                 /* save a copy in cache */
4155                                 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4156                                         if ( !print_hnd->printer_info )
4157                                                 print_hnd->printer_info = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL);
4158
4159                                         if ( print_hnd->printer_info ) {
4160                                                 /* make sure to use the handle's talloc ctx here since 
4161                                                    the printer_2 object must last until the handle is closed */
4162
4163                                                 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4164                                                 
4165                                                 /* don't fail the lookup just because the cache update failed */
4166                                                 if ( !print_hnd->printer_info->info_2 )
4167                                                         DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4168                                         }
4169                                 }
4170                                 *pp_printer = printer;  
4171                         }
4172                         else
4173                                 SAFE_FREE(printer);
4174                         
4175                         break;
4176                         
4177                 default:
4178                         result=WERR_UNKNOWN_LEVEL;
4179                         break;
4180         }
4181         
4182         DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4183
4184         return result;
4185 }
4186
4187 /****************************************************************************
4188  Deletes a NT_PRINTER_INFO_LEVEL struct.
4189 ****************************************************************************/
4190
4191 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4192 {
4193         uint32 result;
4194         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4195
4196         DEBUG(104,("freeing a printer at level [%d]\n", level));
4197
4198         if (printer == NULL)
4199                 return 0;
4200         
4201         switch (level) {
4202                 case 2:
4203                         if (printer->info_2 != NULL) {
4204                                 free_nt_printer_info_level_2(&printer->info_2);
4205                                 result=0;
4206                         } else
4207                                 result=4;
4208                         break;
4209
4210                 default:
4211                         result=1;
4212                         break;
4213         }
4214
4215         SAFE_FREE(*pp_printer);
4216         return result;
4217 }
4218
4219 /****************************************************************************
4220 ****************************************************************************/
4221 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4222 {
4223         uint32 result;
4224         DEBUG(104,("adding a printer at level [%d]\n", level));
4225         dump_a_printer_driver(driver, level);
4226         
4227         switch (level) {
4228                 case 3:
4229                         result=add_a_printer_driver_3(driver.info_3);
4230                         break;
4231
4232                 case 6:
4233                         result=add_a_printer_driver_6(driver.info_6);
4234                         break;
4235
4236                 default:
4237                         result=1;
4238                         break;
4239         }
4240         
4241         return result;
4242 }
4243 /****************************************************************************
4244 ****************************************************************************/
4245
4246 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4247                             fstring drivername, const char *architecture, uint32 version)
4248 {
4249         WERROR result;
4250         
4251         switch (level) {
4252                 case 3:
4253                         /* Sometime we just want any version of the driver */
4254                         
4255                         if ( version == DRIVER_ANY_VERSION ) {
4256                                 /* look for Win2k first and then for NT4 */
4257                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4258                                                 architecture, 3);
4259                                                 
4260                                 if ( !W_ERROR_IS_OK(result) ) {
4261                                         result = get_a_printer_driver_3( &driver->info_3, 
4262                                                         drivername, architecture, 2 );
4263                                 }
4264                         } else {
4265                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4266                                         architecture, version);                         
4267                         }
4268                         break;
4269                         
4270                 default:
4271                         result=W_ERROR(1);
4272                         break;
4273         }
4274         
4275         if (W_ERROR_IS_OK(result))
4276                 dump_a_printer_driver(*driver, level);
4277                 
4278         return result;
4279 }
4280
4281 /****************************************************************************
4282 ****************************************************************************/
4283 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4284 {
4285         uint32 result;
4286         
4287         switch (level) {
4288                 case 3:
4289                 {
4290                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4291                         if (driver.info_3 != NULL)
4292                         {
4293                                 info3=driver.info_3;
4294                                 SAFE_FREE(info3->dependentfiles);
4295                                 ZERO_STRUCTP(info3);
4296                                 SAFE_FREE(info3);
4297                                 result=0;
4298                         } else {
4299                                 result=4;
4300                         }
4301                         break;
4302                 }
4303                 case 6:
4304                 {
4305                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4306                         if (driver.info_6 != NULL) {
4307                                 info6=driver.info_6;
4308                                 SAFE_FREE(info6->dependentfiles);
4309                                 SAFE_FREE(info6->previousnames);
4310                                 ZERO_STRUCTP(info6);
4311                                 SAFE_FREE(info6);
4312                                 result=0;
4313                         } else {
4314                                 result=4;
4315                         }
4316                         break;
4317                 }
4318                 default:
4319                         result=1;
4320                         break;
4321         }
4322         return result;
4323 }
4324
4325
4326 /****************************************************************************
4327   Determine whether or not a particular driver is currently assigned
4328   to a printer
4329 ****************************************************************************/
4330
4331 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4332 {
4333         int snum;
4334         int n_services = lp_numservices();
4335         NT_PRINTER_INFO_LEVEL *printer = NULL;
4336
4337         if ( !info_3 ) 
4338                 return False;
4339
4340         DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4341         
4342         /* loop through the printers.tdb and check for the drivername */
4343         
4344         for (snum=0; snum<n_services; snum++) {
4345                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4346                         continue;
4347                 
4348                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4349                         continue;
4350                 
4351                 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4352                         free_a_printer( &printer, 2 );
4353                         return True;
4354                 }
4355                 
4356                 free_a_printer( &printer, 2 );
4357         }
4358         
4359         DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4360         
4361         /* report that the driver is not in use by default */
4362         
4363         return False;
4364 }
4365
4366
4367 /**********************************************************************
4368  Check to see if a ogiven file is in use by *info
4369  *********************************************************************/
4370  
4371 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4372 {
4373         int i = 0;
4374         
4375         if ( !info )
4376                 return False;
4377                 
4378         if ( strequal(file, info->driverpath) )
4379                 return True;
4380
4381         if ( strequal(file, info->datafile) )
4382                 return True;
4383
4384         if ( strequal(file, info->configfile) )
4385                 return True;
4386
4387         if ( strequal(file, info->helpfile) )
4388                 return True;
4389         
4390         /* see of there are any dependent files to examine */
4391         
4392         if ( !info->dependentfiles )
4393                 return False;
4394         
4395         while ( *info->dependentfiles[i] ) {
4396                 if ( strequal(file, info->dependentfiles[i]) )
4397                         return True;
4398                 i++;
4399         }
4400         
4401         return False;
4402
4403 }
4404
4405 /**********************************************************************
4406  Utility function to remove the dependent file pointed to by the 
4407  input parameter from the list 
4408  *********************************************************************/
4409
4410 static void trim_dependent_file( fstring files[], int idx )
4411 {
4412         
4413         /* bump everything down a slot */
4414
4415         while( *files[idx+1] ) {
4416                 fstrcpy( files[idx], files[idx+1] );
4417                 idx++;
4418         }
4419         
4420         *files[idx] = '\0';
4421
4422         return; 
4423 }
4424
4425 /**********************************************************************
4426  Check if any of the files used by src are also used by drv 
4427  *********************************************************************/
4428
4429 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4430                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4431 {
4432         BOOL    in_use = False;
4433         int     i = 0;
4434         
4435         if ( !src || !drv )
4436                 return False;
4437                 
4438         /* check each file.  Remove it from the src structure if it overlaps */
4439         
4440         if ( drv_file_in_use(src->driverpath, drv) ) {
4441                 in_use = True;
4442                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4443                 fstrcpy( src->driverpath, "" );
4444         }
4445                 
4446         if ( drv_file_in_use(src->datafile, drv) ) {
4447                 in_use = True;
4448                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4449                 fstrcpy( src->datafile, "" );
4450         }
4451                 
4452         if ( drv_file_in_use(src->configfile, drv) ) {
4453                 in_use = True;
4454                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4455                 fstrcpy( src->configfile, "" );
4456         }
4457                 
4458         if ( drv_file_in_use(src->helpfile, drv) ) {
4459                 in_use = True;
4460                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4461                 fstrcpy( src->helpfile, "" );
4462         }
4463         
4464         /* are there any dependentfiles to examine? */
4465         
4466         if ( !src->dependentfiles )
4467                 return in_use;
4468                 
4469         while ( *src->dependentfiles[i] ) {
4470                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4471                         in_use = True;
4472                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4473                         trim_dependent_file( src->dependentfiles, i );
4474                 } else
4475                         i++;
4476         }               
4477                 
4478         return in_use;
4479 }
4480
4481 /****************************************************************************
4482   Determine whether or not a particular driver files are currently being 
4483   used by any other driver.  
4484   
4485   Return value is True if any files were in use by other drivers
4486   and False otherwise.
4487   
4488   Upon return, *info has been modified to only contain the driver files
4489   which are not in use
4490 ****************************************************************************/
4491
4492 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4493 {
4494         int                             i;
4495         int                             ndrivers;
4496         uint32                          version;
4497         fstring                         *list = NULL;
4498         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4499         
4500         if ( !info )
4501                 return False;
4502         
4503         version = info->cversion;
4504         
4505         /* loop over all driver versions */
4506         
4507         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4508         
4509         /* get the list of drivers */
4510                 
4511         list = NULL;
4512         ndrivers = get_ntdrivers(&list, info->environment, version);
4513                 
4514         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4515                 ndrivers, info->environment, version));
4516
4517         /* check each driver for overlap in files */
4518                 
4519         for (i=0; i<ndrivers; i++) {
4520                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4521                         
4522                 ZERO_STRUCT(driver);
4523                         
4524                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4525                         SAFE_FREE(list);
4526                         return True;
4527                 }
4528                         
4529                 /* check if d2 uses any files from d1 */
4530                 /* only if this is a different driver than the one being deleted */
4531                         
4532                 if ( !strequal(info->name, driver.info_3->name) ) {
4533                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4534                                 free_a_printer_driver(driver, 3);
4535                                 SAFE_FREE( list );
4536                                 return True;
4537                         }
4538                 }
4539         
4540                 free_a_printer_driver(driver, 3);
4541         }       
4542         
4543         SAFE_FREE(list);
4544         
4545         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4546         
4547         driver.info_3 = info;
4548         
4549         if ( DEBUGLEVEL >= 20 )
4550                 dump_a_printer_driver( driver, 3 );
4551         
4552         return False;
4553 }
4554
4555 /****************************************************************************
4556   Actually delete the driver files.  Make sure that 
4557   printer_driver_files_in_use() return False before calling 
4558   this.
4559 ****************************************************************************/
4560
4561 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4562 {
4563         int i = 0;
4564         char *s;
4565         connection_struct *conn;
4566         DATA_BLOB null_pw;
4567         NTSTATUS nt_status;
4568         fstring res_type;
4569         BOOL bad_path;
4570         SMB_STRUCT_STAT  st;
4571
4572         if ( !info_3 )
4573                 return False;
4574                 
4575         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4576         
4577         /*
4578          * Connect to the print$ share under the same account as the 
4579          * user connected to the rpc pipe. Note we must be root to 
4580          * do this.
4581          */
4582          
4583         null_pw = data_blob( NULL, 0 );
4584         fstrcpy(res_type, "A:");
4585         become_root();
4586         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4587         unbecome_root();
4588         
4589         if ( !conn ) {
4590                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4591                 return False;
4592         }
4593
4594         /* Save who we are - we are temporarily becoming the connection user. */
4595
4596         if ( !become_user(conn, conn->vuid) ) {
4597                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4598                 return False;
4599         }
4600
4601         /* now delete the files; must strip the '\print$' string from 
4602            fron of path                                                */
4603         
4604         if ( *info_3->driverpath ) {
4605                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4606                         driver_unix_convert(s, conn, NULL, &bad_path, &st);
4607                         DEBUG(10,("deleting driverfile [%s]\n", s));
4608                         unlink_internals(conn, 0, s);
4609                 }
4610         }
4611                 
4612         if ( *info_3->configfile ) {
4613                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4614                         driver_unix_convert(s, conn, NULL, &bad_path, &st);
4615                         DEBUG(10,("deleting configfile [%s]\n", s));
4616                         unlink_internals(conn, 0, s);
4617                 }
4618         }
4619         
4620         if ( *info_3->datafile ) {
4621                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4622                         driver_unix_convert(s, conn, NULL, &bad_path, &st);
4623                         DEBUG(10,("deleting datafile [%s]\n", s));
4624                         unlink_internals(conn, 0, s);
4625                 }
4626         }
4627         
4628         if ( *info_3->helpfile ) {
4629                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4630                         driver_unix_convert(s, conn, NULL, &bad_path, &st);
4631                         DEBUG(10,("deleting helpfile [%s]\n", s));
4632                         unlink_internals(conn, 0, s);
4633                 }
4634         }
4635         
4636         /* check if we are done removing files */
4637         
4638         if ( info_3->dependentfiles ) {
4639                 while ( *info_3->dependentfiles[i] ) {
4640                         char *file;
4641
4642                         /* bypass the "\print$" portion of the path */
4643                         
4644                         if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4645                                 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4646                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4647                                 unlink_internals(conn, 0, file );
4648                         }
4649                         
4650                         i++;
4651                 }
4652         }
4653
4654         unbecome_user();
4655         
4656         return True;
4657 }
4658
4659 /****************************************************************************
4660  Remove a printer driver from the TDB.  This assumes that the the driver was
4661  previously looked up.
4662  ***************************************************************************/
4663
4664 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4665                               uint32 version, BOOL delete_files )
4666 {
4667         pstring         key;
4668         const char     *arch;
4669         TDB_DATA        kbuf, dbuf;
4670         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4671
4672         /* delete the tdb data first */
4673
4674         arch = get_short_archi(info_3->environment);
4675         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4676                 arch, version, info_3->name);
4677
4678         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4679                 key, delete_files ? "TRUE" : "FALSE" ));
4680
4681         ctr.info_3 = info_3;
4682         dump_a_printer_driver( ctr, 3 );
4683
4684         kbuf.dptr=key;
4685         kbuf.dsize=strlen(key)+1;
4686
4687         /* check if the driver actually exists for this environment */
4688         
4689         dbuf = tdb_fetch( tdb_drivers, kbuf );
4690         if ( !dbuf.dptr ) {
4691                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4692                 return WERR_UNKNOWN_PRINTER_DRIVER;
4693         }
4694                 
4695         SAFE_FREE( dbuf.dptr );
4696         
4697         /* ok... the driver exists so the delete should return success */
4698                 
4699         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4700                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4701                 return WERR_ACCESS_DENIED;
4702         }
4703
4704         /*
4705          * now delete any associated files if delete_files == True
4706          * even if this part failes, we return succes because the
4707          * driver doesn not exist any more
4708          */
4709
4710         if ( delete_files )
4711                 delete_driver_files( info_3, user );
4712                         
4713                 
4714         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4715
4716         return WERR_OK;
4717         }
4718         
4719 /****************************************************************************
4720  Store a security desc for a printer.
4721 ****************************************************************************/
4722
4723 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4724 {
4725         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4726         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4727         prs_struct ps;
4728         TALLOC_CTX *mem_ctx = NULL;
4729         fstring key;
4730         WERROR status;
4731
4732         mem_ctx = talloc_init("nt_printing_setsec");
4733         if (mem_ctx == NULL)
4734                 return WERR_NOMEM;
4735
4736         /* The old owner and group sids of the security descriptor are not
4737            present when new ACEs are added or removed by changing printer
4738            permissions through NT.  If they are NULL in the new security
4739            descriptor then copy them over from the old one. */
4740
4741         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4742                 DOM_SID *owner_sid, *group_sid;
4743                 SEC_ACL *dacl, *sacl;
4744                 SEC_DESC *psd = NULL;
4745                 size_t size;
4746
4747                 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4748
4749                 /* Pick out correct owner and group sids */
4750
4751                 owner_sid = secdesc_ctr->sec->owner_sid ?
4752                         secdesc_ctr->sec->owner_sid :
4753                         old_secdesc_ctr->sec->owner_sid;
4754
4755                 group_sid = secdesc_ctr->sec->grp_sid ?
4756                         secdesc_ctr->sec->grp_sid :
4757                         old_secdesc_ctr->sec->grp_sid;
4758
4759                 dacl = secdesc_ctr->sec->dacl ?
4760                         secdesc_ctr->sec->dacl :
4761                         old_secdesc_ctr->sec->dacl;
4762
4763                 sacl = secdesc_ctr->sec->sacl ?
4764                         secdesc_ctr->sec->sacl :
4765                         old_secdesc_ctr->sec->sacl;
4766
4767                 /* Make a deep copy of the security descriptor */
4768
4769                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4770                                     owner_sid, group_sid,
4771                                     sacl,
4772                                     dacl,
4773                                     &size);
4774
4775                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4776         }
4777
4778         if (!new_secdesc_ctr) {
4779                 new_secdesc_ctr = secdesc_ctr;
4780         }
4781
4782         /* Store the security descriptor in a tdb */
4783
4784         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4785                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4786
4787         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4788                              &ps, 1)) {
4789                 status = WERR_BADFUNC;
4790                 goto out;
4791         }
4792
4793         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4794
4795         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4796                 status = WERR_OK;
4797         } else {
4798                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4799                 status = WERR_BADFUNC;
4800         }
4801
4802         /* Free malloc'ed memory */
4803
4804  out:
4805
4806         prs_mem_free(&ps);
4807         if (mem_ctx)
4808                 talloc_destroy(mem_ctx);
4809         return status;
4810 }
4811
4812 /****************************************************************************
4813  Construct a default security descriptor buffer for a printer.
4814 ****************************************************************************/
4815
4816 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4817 {
4818         SEC_ACE ace[5]; /* max number of ace entries */
4819         int i = 0;
4820         SEC_ACCESS sa;
4821         SEC_ACL *psa = NULL;
4822         SEC_DESC_BUF *sdb = NULL;
4823         SEC_DESC *psd = NULL;
4824         DOM_SID owner_sid;
4825         size_t sd_size;
4826
4827         /* Create an ACE where Everyone is allowed to print */
4828
4829         init_sec_access(&sa, PRINTER_ACE_PRINT);
4830         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4831                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4832
4833         /* Make the security descriptor owned by the Administrators group
4834            on the PDC of the domain. */
4835
4836         if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4837                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4838         } else {
4839
4840                 /* Backup plan - make printer owned by admins.
4841                    This should emulate a lanman printer as security
4842                    settings can't be changed. */
4843
4844                 sid_copy(&owner_sid, get_global_sam_sid());
4845                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4846         }
4847
4848         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4849         init_sec_ace(&ace[i++], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4850                      sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4851                      SEC_ACE_FLAG_INHERIT_ONLY);
4852
4853         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4854         init_sec_ace(&ace[i++], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4855                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4856
4857         /* Add the domain admins group if we are a DC */
4858         
4859         if ( IS_DC ) {
4860                 DOM_SID domadmins_sid;
4861                 
4862                 sid_copy(&domadmins_sid, get_global_sam_sid());
4863                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
4864                 
4865                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4866                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4867                              sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4868                              SEC_ACE_FLAG_INHERIT_ONLY);
4869
4870                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4871                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4872                              sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4873         }
4874                      
4875         /* The ACL revision number in rpc_secdesc.h differs from the one
4876            created by NT when setting ACE entries in printer
4877            descriptors.  NT4 complains about the property being edited by a
4878            NT5 machine. */
4879
4880         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
4881                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4882                                     &owner_sid, NULL,
4883                                     NULL, psa, &sd_size);
4884         }
4885
4886         if (!psd) {
4887                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4888                 return NULL;
4889         }
4890
4891         sdb = make_sec_desc_buf(ctx, sd_size, psd);
4892
4893         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4894                  (unsigned int)sd_size));
4895
4896         return sdb;
4897 }
4898
4899 /****************************************************************************
4900  Get a security desc for a printer.
4901 ****************************************************************************/
4902
4903 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4904 {
4905         prs_struct ps;
4906         fstring key;
4907         char *temp;
4908
4909         if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4910                 printername = temp + 1;
4911         }
4912
4913         /* Fetch security descriptor from tdb */
4914
4915         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4916
4917         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4918             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4919
4920                 DEBUG(4,("using default secdesc for %s\n", printername));
4921
4922                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4923                         return False;
4924                 }
4925
4926                 /* Save default security descriptor for later */
4927
4928                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4929                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4930
4931                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4932                         tdb_prs_store(tdb_printers, key, &ps);
4933
4934                 prs_mem_free(&ps);
4935
4936                 return True;
4937         }
4938
4939         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4940            this security descriptor has been created when winbindd was
4941            down.  Take ownership of security descriptor. */
4942
4943         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4944                 DOM_SID owner_sid;
4945
4946                 /* Change sd owner to workgroup administrator */
4947
4948                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4949                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4950                         SEC_DESC *psd = NULL;
4951                         size_t size;
4952
4953                         /* Create new sd */
4954
4955                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4956
4957                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4958                                             &owner_sid,
4959                                             (*secdesc_ctr)->sec->grp_sid,
4960                                             (*secdesc_ctr)->sec->sacl,
4961                                             (*secdesc_ctr)->sec->dacl,
4962                                             &size);
4963
4964                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4965
4966                         /* Swap with other one */
4967
4968                         *secdesc_ctr = new_secdesc_ctr;
4969
4970                         /* Set it */
4971
4972                         nt_printing_setsec(printername, *secdesc_ctr);
4973                 }
4974         }
4975
4976         if (DEBUGLEVEL >= 10) {
4977                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4978                 int i;
4979
4980                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4981                            printername, the_acl->num_aces));
4982
4983                 for (i = 0; i < the_acl->num_aces; i++) {
4984                         fstring sid_str;
4985
4986                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4987
4988                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4989                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
4990                                    the_acl->ace[i].info.mask)); 
4991                 }
4992         }
4993
4994         prs_mem_free(&ps);
4995         return True;
4996 }
4997
4998 /* error code:
4999         0: everything OK
5000         1: level not implemented
5001         2: file doesn't exist
5002         3: can't allocate memory
5003         4: can't free memory
5004         5: non existant struct
5005 */
5006
5007 /*
5008         A printer and a printer driver are 2 different things.
5009         NT manages them separatelly, Samba does the same.
5010         Why ? Simply because it's easier and it makes sense !
5011         
5012         Now explanation: You have 3 printers behind your samba server,
5013         2 of them are the same make and model (laser A and B). But laser B
5014         has an 3000 sheet feeder and laser A doesn't such an option.
5015         Your third printer is an old dot-matrix model for the accounting :-).
5016         
5017         If the /usr/local/samba/lib directory (default dir), you will have
5018         5 files to describe all of this.
5019         
5020         3 files for the printers (1 by printer):
5021                 NTprinter_laser A
5022                 NTprinter_laser B
5023                 NTprinter_accounting
5024         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5025                 NTdriver_printer model X
5026                 NTdriver_printer model Y
5027
5028 jfm: I should use this comment for the text file to explain
5029         same thing for the forms BTW.
5030         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5031
5032 */
5033
5034 /* Convert generic access rights to printer object specific access rights.
5035    It turns out that NT4 security descriptors use generic access rights and
5036    NT5 the object specific ones. */
5037
5038 void map_printer_permissions(SEC_DESC *sd)
5039 {
5040         int i;
5041
5042         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5043                 se_map_generic(&sd->dacl->ace[i].info.mask,
5044                                &printer_generic_mapping);
5045         }
5046 }
5047
5048 /****************************************************************************
5049  Check a user has permissions to perform the given operation.  We use the
5050  permission constants defined in include/rpc_spoolss.h to check the various
5051  actions we perform when checking printer access.
5052
5053    PRINTER_ACCESS_ADMINISTER:
5054        print_queue_pause, print_queue_resume, update_printer_sec,
5055        update_printer, spoolss_addprinterex_level_2,
5056        _spoolss_setprinterdata
5057
5058    PRINTER_ACCESS_USE:
5059        print_job_start
5060
5061    JOB_ACCESS_ADMINISTER:
5062        print_job_delete, print_job_pause, print_job_resume,
5063        print_queue_purge
5064
5065   Try access control in the following order (for performance reasons):
5066     1)  root ans SE_PRINT_OPERATOR can do anything (easy check) 
5067     2)  check security descriptor (bit comparisons in memory)
5068     3)  "printer admins" (may result in numerous calls to winbind)
5069
5070  ****************************************************************************/
5071 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5072 {
5073         SEC_DESC_BUF *secdesc = NULL;
5074         uint32 access_granted;
5075         NTSTATUS status;
5076         BOOL result;
5077         const char *pname;
5078         TALLOC_CTX *mem_ctx = NULL;
5079         extern struct current_user current_user;
5080         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5081         
5082         /* If user is NULL then use the current_user structure */
5083
5084         if (!user)
5085                 user = &current_user;
5086
5087         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5088
5089         if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5090                 return True;
5091         }
5092
5093         /* Get printer name */
5094
5095         pname = PRINTERNAME(snum);
5096
5097         if (!pname || !*pname) {
5098                 errno = EACCES;
5099                 return False;
5100         }
5101
5102         /* Get printer security descriptor */
5103
5104         if(!(mem_ctx = talloc_init("print_access_check"))) {
5105                 errno = ENOMEM;
5106                 return False;
5107         }
5108
5109         nt_printing_getsec(mem_ctx, pname, &secdesc);
5110
5111         if (access_type == JOB_ACCESS_ADMINISTER) {
5112                 SEC_DESC_BUF *parent_secdesc = secdesc;
5113
5114                 /* Create a child security descriptor to check permissions
5115                    against.  This is because print jobs are child objects
5116                    objects of a printer. */
5117
5118                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5119
5120                 /* Now this is the bit that really confuses me.  The access
5121                    type needs to be changed from JOB_ACCESS_ADMINISTER to
5122                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
5123                    to do with the child (job) object becoming like a
5124                    printer??  -tpot */
5125
5126                 access_type = PRINTER_ACCESS_ADMINISTER;
5127         }
5128         
5129         /* Check access */
5130         
5131         map_printer_permissions(secdesc->sec);
5132
5133         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5134                                  &access_granted, &status);
5135
5136         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5137
5138         /* see if we need to try the printer admin list */
5139
5140         if ( access_granted == 0 ) {
5141                 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5142                         return True;
5143         }
5144
5145         talloc_destroy(mem_ctx);
5146         
5147         if (!result)
5148                 errno = EACCES;
5149
5150         return result;
5151 }
5152
5153 /****************************************************************************
5154  Check the time parameters allow a print operation.
5155 *****************************************************************************/
5156
5157 BOOL print_time_access_check(int snum)
5158 {
5159         NT_PRINTER_INFO_LEVEL *printer = NULL;
5160         BOOL ok = False;
5161         time_t now = time(NULL);
5162         struct tm *t;
5163         uint32 mins;
5164
5165         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5166                 return False;
5167
5168         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5169                 ok = True;
5170
5171         t = gmtime(&now);
5172         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5173
5174         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5175                 ok = True;
5176
5177         free_a_printer(&printer, 2);
5178
5179         if (!ok)
5180                 errno = EACCES;
5181
5182         return ok;
5183 }
5184
5185 /****************************************************************************
5186  Fill in the servername sent in the _spoolss_open_printer_ex() call
5187 ****************************************************************************/
5188 char* get_server_name( Printer_entry *printer )
5189 {
5190         return printer->servername;
5191 }