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