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