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