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