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