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