Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header.
[metze/samba/wip.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000.
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 pstring global_myname;
26 extern DOM_SID global_sid_World;
27
28 static TDB_CONTEXT *tdb_forms; /* used for forms files */
29 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
30 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
35 #define PRINTERS_PREFIX "PRINTERS/"
36 #define SECDESC_PREFIX "SECDESC/"
37  
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40  
41 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_2
42
43 /* Map generic permissions to printer object specific permissions */
44
45 struct generic_mapping printer_generic_mapping = {
46         PRINTER_READ,
47         PRINTER_WRITE,
48         PRINTER_EXECUTE,
49         PRINTER_ALL_ACCESS
50 };
51
52 /* We need one default form to support our default printer. Msoft adds the
53 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
54 array index). Letter is always first, so (for the current code) additions
55 always put things in the correct order. */
56 static nt_forms_struct default_forms[] = {
57         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
58         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
59         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
60         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
61         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
62         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
63         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
64         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
65         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
66         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
67         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
68         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
69         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
70         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
71         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
72         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
73         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
74         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
75         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
76         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
77         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
78         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
79         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
80         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
81         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
82         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
83         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
84         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
85         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
86         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
87         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
88         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
89         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
90         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
91         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
92         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
93         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
94         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
95         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
96         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
97         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
98         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
99         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
100         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
101         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
102         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
103         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
104         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
105         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
106         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
107         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
108         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
109         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
110         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
111         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
112         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
113         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
114         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
115         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
116         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
117         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
118         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
119         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
120         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
121         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
122         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
123         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
124         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
125         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
126         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
127         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
128         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
129         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
130         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
131         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
132         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
133         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
134         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
135         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
136         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
137         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
138         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
139         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
140         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
141         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
142         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
143         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
144         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
145         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
146         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
147         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
148         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
149         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
150         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
151         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
152         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
153         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
154         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
155         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
156         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
157         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
158         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
159         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
160         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
161         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
162         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
163         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
164         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
165         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
166         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
167         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
168         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
169         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
170         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
171         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
172         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
173         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
174         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
175 };
176
177 static BOOL upgrade_to_version_2(void)
178 {
179         TDB_DATA kbuf, newkey, dbuf;
180  
181         DEBUG(0,("upgrade_to_version_2: upgrading print tdb's to version 2\n"));
182  
183         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
184                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
185
186                 dbuf = tdb_fetch(tdb_drivers, kbuf);
187
188                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
189                         DEBUG(0,("upgrade_to_version_2:moving form\n"));
190                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
191                                 DEBUG(0,("upgrade_to_version_2: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
192                                 return False;
193                         }
194                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
195                                 DEBUG(0,("upgrade_to_version_2: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
196                                 return False;
197                         }
198                 }
199  
200                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
201                         DEBUG(0,("upgrade_to_version_2:moving printer\n"));
202                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
203                                 DEBUG(0,("upgrade_to_version_2: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
204                                 return False;
205                         }
206                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
207                                 DEBUG(0,("upgrade_to_version_2: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
208                                 return False;
209                         }
210                 }
211  
212                 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
213                         DEBUG(0,("upgrade_to_version_2:moving secdesc\n"));
214                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
215                                 DEBUG(0,("upgrade_to_version_2: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
216                                 return False;
217                         }
218                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
219                                 DEBUG(0,("upgrade_to_version_2: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
220                                 return False;
221                         }
222                 }
223  
224                 SAFE_FREE(dbuf.dptr);
225         }
226
227         return True;
228 }
229
230 /****************************************************************************
231 open the NT printing tdb
232 ****************************************************************************/
233 BOOL nt_printing_init(void)
234 {
235         static pid_t local_pid;
236         char *vstring = "INFO/version";
237
238         if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
239                 return True;
240  
241         tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
242         if (!tdb_drivers) {
243                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
244                         lock_path("ntdrivers.tdb"), strerror(errno) ));
245                 return False;
246         }
247  
248         tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
249         if (!tdb_printers) {
250                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
251                         lock_path("ntprinters.tdb"), strerror(errno) ));
252                 return False;
253         }
254  
255         tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
256         if (!tdb_forms) {
257                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
258                         lock_path("ntforms.tdb"), strerror(errno) ));
259                 return False;
260         }
261  
262         local_pid = sys_getpid();
263  
264         /* handle a Samba upgrade */
265         tdb_lock_bystring(tdb_drivers, vstring);
266         if (tdb_fetch_int(tdb_drivers, vstring) != NTDRIVERS_DATABASE_VERSION) {
267  
268                 if (tdb_fetch_int(tdb_drivers, vstring) == NTDRIVERS_DATABASE_VERSION_1) {
269                         if (!upgrade_to_version_2())
270                                 return False;
271                 } else
272                         tdb_traverse(tdb_drivers, (tdb_traverse_func)tdb_delete, NULL);
273  
274                 tdb_store_int(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
275         }
276         tdb_unlock_bystring(tdb_drivers, vstring);
277
278         return True;
279 }
280
281 /****************************************************************************
282  get builtin form struct list
283 ****************************************************************************/
284 int get_builtin_ntforms(nt_forms_struct **list)
285 {
286         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
287         return sizeof(default_forms) / sizeof(default_forms[0]);
288 }
289
290 /****************************************************************************
291  get a builtin form struct
292 ****************************************************************************/
293
294 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
295 {
296         int i,count;
297         fstring form_name;
298         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
299         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
300         count = sizeof(default_forms) / sizeof(default_forms[0]);
301         for (i=0;i<count;i++) {
302                 if (strequal(form_name,default_forms[i].name)) {
303                         DEBUGADD(6,("Found builtin form %s \n", form_name));
304                         memcpy(form,&default_forms[i],sizeof(*form));
305                         break;
306                 }
307         }
308
309         return (i !=count);
310 }
311
312 /****************************************************************************
313 get a form struct list
314 ****************************************************************************/
315 int get_ntforms(nt_forms_struct **list)
316 {
317         TDB_DATA kbuf, newkey, dbuf;
318         nt_forms_struct *tl;
319         nt_forms_struct form;
320         int ret;
321         int i;
322         int n = 0;
323
324         for (kbuf = tdb_firstkey(tdb_forms);
325              kbuf.dptr;
326              newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
327                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
328                 
329                 dbuf = tdb_fetch(tdb_forms, kbuf);
330                 if (!dbuf.dptr) continue;
331
332                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
333                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
334                                  &i, &form.flag, &form.width, &form.length, &form.left,
335                                  &form.top, &form.right, &form.bottom);
336                 SAFE_FREE(dbuf.dptr);
337                 if (ret != dbuf.dsize) continue;
338
339                 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
340                 if (!tl) {
341                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
342                         return 0;
343                 }
344                 *list = tl;
345                 (*list)[n] = form;
346                 n++;
347         }
348         
349
350         return n;
351 }
352
353 /****************************************************************************
354 write a form struct list
355 ****************************************************************************/
356 int write_ntforms(nt_forms_struct **list, int number)
357 {
358         pstring buf, key;
359         int len;
360         TDB_DATA kbuf,dbuf;
361         int i;
362
363         for (i=0;i<number;i++) {
364                 /* save index, so list is rebuilt in correct order */
365                 len = tdb_pack(buf, sizeof(buf), "dddddddd",
366                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
367                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
368                                (*list)[i].bottom);
369                 if (len > sizeof(buf)) break;
370                 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
371                 kbuf.dsize = strlen(key)+1;
372                 kbuf.dptr = key;
373                 dbuf.dsize = len;
374                 dbuf.dptr = buf;
375                 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
376        }
377
378        return i;
379 }
380
381 /****************************************************************************
382 add a form struct at the end of the list
383 ****************************************************************************/
384 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
385 {
386         int n=0;
387         BOOL update;
388         fstring form_name;
389         nt_forms_struct *tl;
390
391         /*
392          * NT tries to add forms even when
393          * they are already in the base
394          * only update the values if already present
395          */
396
397         update=False;
398         
399         unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
400         for (n=0; n<*count; n++) {
401                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
402                         DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
403                         update=True;
404                         break;
405                 }
406         }
407
408         if (update==False) {
409                 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
410                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
411                         return False;
412                 }
413                 *list = tl;
414                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
415                 (*count)++;
416         }
417         
418         (*list)[n].flag=form->flags;
419         (*list)[n].width=form->size_x;
420         (*list)[n].length=form->size_y;
421         (*list)[n].left=form->left;
422         (*list)[n].top=form->top;
423         (*list)[n].right=form->right;
424         (*list)[n].bottom=form->bottom;
425
426         return True;
427 }
428
429 /****************************************************************************
430  delete a named form struct
431 ****************************************************************************/
432 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
433 {
434         pstring key;
435         TDB_DATA kbuf;
436         int n=0;
437         fstring form_name;
438
439         *ret = WERR_OK;
440
441         unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
442
443         for (n=0; n<*count; n++) {
444                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
445                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
446                         break;
447                 }
448         }
449
450         if (n == *count) {
451                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
452                 *ret = WERR_INVALID_PARAM;
453                 return False;
454         }
455
456         slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
457         kbuf.dsize = strlen(key)+1;
458         kbuf.dptr = key;
459         if (tdb_delete(tdb_forms, kbuf) != 0) {
460                 *ret = WERR_NOMEM;
461                 return False;
462         }
463
464         return True;
465 }
466
467 /****************************************************************************
468 update a form struct
469 ****************************************************************************/
470 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
471 {
472         int n=0;
473         fstring form_name;
474         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
475
476         DEBUG(106, ("[%s]\n", form_name));
477         for (n=0; n<count; n++)
478         {
479                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
480                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
481                         break;
482         }
483
484         if (n==count) return;
485
486         (*list)[n].flag=form->flags;
487         (*list)[n].width=form->size_x;
488         (*list)[n].length=form->size_y;
489         (*list)[n].left=form->left;
490         (*list)[n].top=form->top;
491         (*list)[n].right=form->right;
492         (*list)[n].bottom=form->bottom;
493 }
494
495 /****************************************************************************
496 get the nt drivers list
497
498 traverse the database and look-up the matching names
499 ****************************************************************************/
500 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
501 {
502         int total=0;
503         fstring short_archi;
504         fstring *fl;
505         pstring key;
506         TDB_DATA kbuf, newkey;
507
508         get_short_archi(short_archi, architecture);
509         slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
510
511         for (kbuf = tdb_firstkey(tdb_drivers);
512              kbuf.dptr;
513              newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
514                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
515                 
516                 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
517                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
518                         return -1;
519                 }
520                 else *list = fl;
521
522                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
523                 total++;
524         }
525
526         return(total);
527 }
528
529 /****************************************************************************
530 function to do the mapping between the long architecture name and
531 the short one.
532 ****************************************************************************/
533 BOOL get_short_archi(char *short_archi, char *long_archi)
534 {
535         struct table {
536                 char *long_archi;
537                 char *short_archi;
538         };
539         
540         struct table archi_table[]=
541         {
542                 {"Windows 4.0",          "WIN40"    },
543                 {"Windows NT x86",       "W32X86"   },
544                 {"Windows NT R4000",     "W32MIPS"  },
545                 {"Windows NT Alpha_AXP", "W32ALPHA" },
546                 {"Windows NT PowerPC",   "W32PPC"   },
547                 {NULL,                   ""         }
548         };
549         
550         int i=-1;
551
552         DEBUG(107,("Getting architecture dependant directory\n"));
553         do {
554                 i++;
555         } while ( (archi_table[i].long_archi!=NULL ) &&
556                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
557
558         if (archi_table[i].long_archi==NULL) {
559                 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
560                 return False;
561         }
562
563         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
564
565         DEBUGADD(108,("index: [%d]\n", i));
566         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
567         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
568         
569         return True;
570 }
571
572 /****************************************************************************
573 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
574 There are two case to be covered here: PE (Portable Executable) and NE (New
575 Executable) files. Both files support the same INFO structure, but PE files
576 store the signature in unicode, and NE files store it as !unicode.
577 ****************************************************************************/
578 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
579                                                          uint32 *minor)
580 {
581         int     i;
582         char    *buf;
583         ssize_t byte_count;
584
585         if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
586                 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
587                                 fname, PE_HEADER_SIZE));
588                 goto error_exit;
589         }
590
591         /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
592         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
593                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
594                                 fname, byte_count));
595                 goto no_version_info;
596         }
597
598         /* Is this really a DOS header? */
599         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
600                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
601                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
602                 goto no_version_info;
603         }
604
605         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
606         if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
607                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
608                                 fname, errno));
609                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
610                 goto no_version_info;
611         }
612
613         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
614                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
615                                 fname, byte_count));
616                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
617                 goto no_version_info;
618         }
619
620         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
621         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
622                 int num_sections;
623                 int section_table_bytes;
624                 
625                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
626                         DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
627                                         fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
628                         /* At this point, we assume the file is in error. It still could be somthing
629                          * else besides a PE file, but it unlikely at this point.
630                          */
631                         goto error_exit;
632                 }
633
634                 /* get the section table */
635                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
636                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
637                 SAFE_FREE(buf);
638                 if ((buf=malloc(section_table_bytes)) == NULL) {
639                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
640                                         fname, section_table_bytes));
641                         goto error_exit;
642                 }
643
644                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
645                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
646                                         fname, byte_count));
647                         goto error_exit;
648                 }
649
650                 /* Iterate the section table looking for the resource section ".rsrc" */
651                 for (i = 0; i < num_sections; i++) {
652                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
653
654                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
655                                 int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
656                                 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
657
658                                 SAFE_FREE(buf);
659                                 if ((buf=malloc(section_bytes)) == NULL) {
660                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
661                                                         fname, section_bytes));
662                                         goto error_exit;
663                                 }
664
665                                 /* Seek to the start of the .rsrc section info */
666                                 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
667                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
668                                                         fname, errno));
669                                         goto error_exit;
670                                 }
671
672                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
673                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
674                                                         fname, byte_count));
675                                         goto error_exit;
676                                 }
677
678                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
679                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
680                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
681                                                 /* Align to next long address */
682                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
683
684                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
685                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
686                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
687                                                         
688                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
689                                                                           fname, *major, *minor,
690                                                                           (*major>>16)&0xffff, *major&0xffff,
691                                                                           (*minor>>16)&0xffff, *minor&0xffff));
692                                                         SAFE_FREE(buf);
693                                                         return True;
694                                                 }
695                                         }
696                                 }
697                         }
698                 }
699
700                 /* Version info not found, fall back to origin date/time */
701                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
702                 SAFE_FREE(buf);
703                 return False;
704
705         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
706                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
707                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
708                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
709                         /* At this point, we assume the file is in error. It still could be somthing
710                          * else besides a NE file, but it unlikely at this point. */
711                         goto error_exit;
712                 }
713
714                 /* Allocate a bit more space to speed up things */
715                 SAFE_FREE(buf);
716                 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
717                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
718                                         fname, PE_HEADER_SIZE));
719                         goto error_exit;
720                 }
721
722                 /* This is a HACK! I got tired of trying to sort through the messy
723                  * 'NE' file format. If anyone wants to clean this up please have at
724                  * it, but this works. 'NE' files will eventually fade away. JRR */
725                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
726                         /* Cover case that should not occur in a well formed 'NE' .dll file */
727                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
728
729                         for(i=0; i<byte_count; i++) {
730                                 /* Fast skip past data that can't possibly match */
731                                 if (buf[i] != 'V') continue;
732
733                                 /* Potential match data crosses buf boundry, move it to beginning
734                                  * of buf, and fill the buf with as much as it will hold. */
735                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
736                                         int bc;
737
738                                         memcpy(buf, &buf[i], byte_count-i);
739                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
740                                                                    (byte_count-i))) < 0) {
741
742                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
743                                                                  fname, errno));
744                                                 goto error_exit;
745                                         }
746
747                                         byte_count = bc + (byte_count - i);
748                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
749
750                                         i = 0;
751                                 }
752
753                                 /* Check that the full signature string and the magic number that
754                                  * follows exist (not a perfect solution, but the chances that this
755                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
756                                  * twice, as it is simpler to read the code. */
757                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
758                                         /* Compute skip alignment to next long address */
759                                         int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
760                                                                  sizeof(VS_SIGNATURE)) & 3;
761                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
762
763                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
764                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
765                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
766                                                           fname, *major, *minor,
767                                                           (*major>>16)&0xffff, *major&0xffff,
768                                                           (*minor>>16)&0xffff, *minor&0xffff));
769                                         SAFE_FREE(buf);
770                                         return True;
771                                 }
772                         }
773                 }
774
775                 /* Version info not found, fall back to origin date/time */
776                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
777                 SAFE_FREE(buf);
778                 return False;
779
780         } else
781                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
782                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
783                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
784
785         no_version_info:
786                 SAFE_FREE(buf);
787                 return False;
788
789         error_exit:
790                 SAFE_FREE(buf);
791                 return -1;
792 }
793
794 /****************************************************************************
795 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
796 share one or more files. During the MS installation process files are checked
797 to insure that only a newer version of a shared file is installed over an
798 older version. There are several possibilities for this comparison. If there
799 is no previous version, the new one is newer (obviously). If either file is
800 missing the version info structure, compare the creation date (on Unix use
801 the modification date). Otherwise chose the numerically larger version number.
802 ****************************************************************************/
803 static int file_version_is_newer(connection_struct *conn, fstring new_file,
804                                                                 fstring old_file)
805 {
806         BOOL   use_version = True;
807         pstring filepath;
808
809         uint32 new_major;
810         uint32 new_minor;
811         time_t new_create_time;
812
813         uint32 old_major;
814         uint32 old_minor;
815         time_t old_create_time;
816
817         int access_mode;
818         int action;
819         files_struct    *fsp = NULL;
820         SMB_STRUCT_STAT st;
821         SMB_STRUCT_STAT stat_buf;
822         BOOL bad_path;
823
824         ZERO_STRUCT(st);
825         ZERO_STRUCT(stat_buf);
826         new_create_time = (time_t)0;
827         old_create_time = (time_t)0;
828
829         /* Get file version info (if available) for previous file (if it exists) */
830         pstrcpy(filepath, old_file);
831
832         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
833
834         fsp = open_file_shared(conn, filepath, &stat_buf,
835                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
836                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
837                                                    0, 0, &access_mode, &action);
838         if (!fsp) {
839                 /* Old file not found, so by definition new file is in fact newer */
840                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
841                                 filepath, errno));
842                 return True;
843
844         } else {
845                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
846                 if (ret == -1) goto error_exit;
847
848                 if (!ret) {
849                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
850                                          old_file));
851                         use_version = False;
852                         if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
853                         old_create_time = st.st_mtime;
854                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
855                 }
856         }
857         close_file(fsp, True);
858
859         /* Get file version info (if available) for new file */
860         pstrcpy(filepath, new_file);
861         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
862
863         fsp = open_file_shared(conn, filepath, &stat_buf,
864                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
865                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
866                                                    0, 0, &access_mode, &action);
867         if (!fsp) {
868                 /* New file not found, this shouldn't occur if the caller did its job */
869                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
870                                 filepath, errno));
871                 goto error_exit;
872
873         } else {
874                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
875                 if (ret == -1) goto error_exit;
876
877                 if (!ret) {
878                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
879                                          new_file));
880                         use_version = False;
881                         if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
882                         new_create_time = st.st_mtime;
883                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
884                 }
885         }
886         close_file(fsp, True);
887
888         if (use_version) {
889                 /* Compare versions and choose the larger version number */
890                 if (new_major > old_major ||
891                         (new_major == old_major && new_minor > old_minor)) {
892                         
893                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
894                         return True;
895                 }
896                 else {
897                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
898                         return False;
899                 }
900
901         } else {
902                 /* Compare modification time/dates and choose the newest time/date */
903                 if (new_create_time > old_create_time) {
904                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
905                         return True;
906                 }
907                 else {
908                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
909                         return False;
910                 }
911         }
912
913         error_exit:
914                 if(fsp)
915                         close_file(fsp, True);
916                 return -1;
917 }
918
919 /****************************************************************************
920 Determine the correct cVersion associated with an architecture and driver
921 ****************************************************************************/
922 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
923                                    struct current_user *user, WERROR *perr)
924 {
925         int               cversion;
926         int               access_mode;
927         int               action;
928         NTSTATUS          nt_status;
929         pstring           driverpath;
930         fstring           null_pw;
931         files_struct      *fsp = NULL;
932         BOOL              bad_path;
933         SMB_STRUCT_STAT   st;
934         connection_struct *conn;
935
936         ZERO_STRUCT(st);
937
938         /* If architecture is Windows 95/98/ME, the version is always 0. */
939         if (strcmp(architecture, "WIN40") == 0) {
940                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
941                 return 0;
942         }
943
944         /* connect to the print$ share under the same account as the user connected to the rpc pipe */  
945         /* Null password is ok - we are already an authenticated user... */
946         *null_pw = '\0';
947         conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status);
948
949         if (conn == NULL) {
950                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
951                 *perr = ntstatus_to_werror(nt_status);
952                 return -1;
953         }
954
955         /* Save who we are - we are temporarily becoming the connection user. */
956         push_sec_ctx();
957
958         if (!become_user(conn, conn->vuid)) {
959                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
960                 *perr = WERR_ACCESS_DENIED;
961                 pop_sec_ctx();
962                 return -1;
963         }
964
965         /* Open the driver file (Portable Executable format) and determine the
966          * deriver the cversion. */
967         slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
968
969         unix_convert(driverpath,conn,NULL,&bad_path,&st);
970
971         fsp = open_file_shared(conn, driverpath, &st,
972                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
973                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
974                                                    0, 0, &access_mode, &action);
975         if (!fsp) {
976                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
977                                 driverpath, errno));
978                 *perr = WERR_ACCESS_DENIED;
979                 goto error_exit;
980         }
981         else {
982                 uint32 major;
983                 uint32 minor;
984                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
985                 if (ret == -1) goto error_exit;
986
987                 if (!ret) {
988                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
989                         goto error_exit;
990                 }
991
992                 /*
993                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
994                  * for more details. Version in this case is not just the version of the 
995                  * file, but the version in the sense of kernal mode (2) vs. user mode
996                  * (3) drivers. Other bits of the version fields are the version info. 
997                  * JRR 010716
998                 */
999                 cversion = major & 0x0000ffff;
1000                 switch (cversion) {
1001                         case 2: /* WinNT drivers */
1002                         case 3: /* Win2K drivers */
1003                                 break;
1004                         
1005                         default:
1006                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1007                                         driverpath, cversion));
1008                                 goto error_exit;
1009                 }
1010
1011                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1012                                   driverpath, major, minor));
1013         }
1014
1015         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1016                   driverpath, cversion));
1017
1018         close_file(fsp, True);
1019         close_cnum(conn, user->vuid);
1020         pop_sec_ctx();
1021         return cversion;
1022
1023
1024         error_exit:
1025         if(fsp)
1026                 close_file(fsp, True);
1027         
1028         close_cnum(conn, user->vuid);
1029         pop_sec_ctx();
1030         return -1;
1031 }
1032
1033 /****************************************************************************
1034 ****************************************************************************/
1035 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1036                                              struct current_user *user)
1037 {
1038         fstring architecture;
1039         fstring new_name;
1040         char *p;
1041         int i;
1042         WERROR err;
1043
1044         /* clean up the driver name.
1045          * we can get .\driver.dll
1046          * or worse c:\windows\system\driver.dll !
1047          */
1048         /* using an intermediate string to not have overlaping memcpy()'s */
1049         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1050                 fstrcpy(new_name, p+1);
1051                 fstrcpy(driver->driverpath, new_name);
1052         }
1053
1054         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1055                 fstrcpy(new_name, p+1);
1056                 fstrcpy(driver->datafile, new_name);
1057         }
1058
1059         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1060                 fstrcpy(new_name, p+1);
1061                 fstrcpy(driver->configfile, new_name);
1062         }
1063
1064         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1065                 fstrcpy(new_name, p+1);
1066                 fstrcpy(driver->helpfile, new_name);
1067         }
1068
1069         if (driver->dependentfiles) {
1070                 for (i=0; *driver->dependentfiles[i]; i++) {
1071                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1072                                 fstrcpy(new_name, p+1);
1073                                 fstrcpy(driver->dependentfiles[i], new_name);
1074                         }
1075                 }
1076         }
1077
1078         get_short_archi(architecture, driver->environment);
1079         
1080         /* jfm:7/16/2000 the client always sends the cversion=0.
1081          * The server should check which version the driver is by reading
1082          * the PE header of driver->driverpath.
1083          *
1084          * For Windows 95/98 the version is 0 (so the value sent is correct)
1085          * For Windows NT (the architecture doesn't matter)
1086          *      NT 3.1: cversion=0
1087          *      NT 3.5/3.51: cversion=1
1088          *      NT 4: cversion=2
1089          *      NT2K: cversion=3
1090          */
1091         if ((driver->cversion = get_correct_cversion( architecture,
1092                                                       driver->driverpath, user, &err)) == -1)
1093                 return err;
1094
1095         return WERR_OK;
1096 }
1097         
1098 /****************************************************************************
1099 ****************************************************************************/
1100 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1101                                              struct current_user *user)
1102 {
1103         fstring architecture;
1104         fstring new_name;
1105         char *p;
1106         int i;
1107         WERROR err;
1108
1109         /* clean up the driver name.
1110          * we can get .\driver.dll
1111          * or worse c:\windows\system\driver.dll !
1112          */
1113         /* using an intermediate string to not have overlaping memcpy()'s */
1114         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1115                 fstrcpy(new_name, p+1);
1116                 fstrcpy(driver->driverpath, new_name);
1117         }
1118
1119         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1120                 fstrcpy(new_name, p+1);
1121                 fstrcpy(driver->datafile, new_name);
1122         }
1123
1124         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1125                 fstrcpy(new_name, p+1);
1126                 fstrcpy(driver->configfile, new_name);
1127         }
1128
1129         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1130                 fstrcpy(new_name, p+1);
1131                 fstrcpy(driver->helpfile, new_name);
1132         }
1133
1134         if (driver->dependentfiles) {
1135                 for (i=0; *driver->dependentfiles[i]; i++) {
1136                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1137                                 fstrcpy(new_name, p+1);
1138                                 fstrcpy(driver->dependentfiles[i], new_name);
1139                         }
1140                 }
1141         }
1142
1143         get_short_archi(architecture, driver->environment);
1144
1145         /* jfm:7/16/2000 the client always sends the cversion=0.
1146          * The server should check which version the driver is by reading
1147          * the PE header of driver->driverpath.
1148          *
1149          * For Windows 95/98 the version is 0 (so the value sent is correct)
1150          * For Windows NT (the architecture doesn't matter)
1151          *      NT 3.1: cversion=0
1152          *      NT 3.5/3.51: cversion=1
1153          *      NT 4: cversion=2
1154          *      NT2K: cversion=3
1155          */
1156         if ((driver->version = get_correct_cversion(architecture,
1157                                                     driver->driverpath, user, &err)) == -1)
1158                 return err;
1159
1160         return WERR_OK;
1161 }
1162
1163 /****************************************************************************
1164 ****************************************************************************/
1165 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1166                                                           uint32 level, struct current_user *user)
1167 {
1168         switch (level) {
1169                 case 3:
1170                 {
1171                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1172                         driver=driver_abstract.info_3;
1173                         return clean_up_driver_struct_level_3(driver, user);
1174                 }
1175                 case 6:
1176                 {
1177                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1178                         driver=driver_abstract.info_6;
1179                         return clean_up_driver_struct_level_6(driver, user);
1180                 }
1181                 default:
1182                         return WERR_INVALID_PARAM;
1183         }
1184 }
1185
1186 /****************************************************************************
1187  This function sucks and should be replaced. JRA.
1188 ****************************************************************************/
1189
1190 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1191 {
1192     dst->cversion  = src->version;
1193
1194     fstrcpy( dst->name, src->name);
1195     fstrcpy( dst->environment, src->environment);
1196     fstrcpy( dst->driverpath, src->driverpath);
1197     fstrcpy( dst->datafile, src->datafile);
1198     fstrcpy( dst->configfile, src->configfile);
1199     fstrcpy( dst->helpfile, src->helpfile);
1200     fstrcpy( dst->monitorname, src->monitorname);
1201     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1202     dst->dependentfiles = src->dependentfiles;
1203 }
1204
1205 #if 0 /* Debugging function */
1206
1207 static char* ffmt(unsigned char *c){
1208         int i;
1209         static char ffmt_str[17];
1210
1211         for (i=0; i<16; i++) {
1212                 if ((c[i] < ' ') || (c[i] > '~'))
1213                         ffmt_str[i]='.';
1214                 else
1215                         ffmt_str[i]=c[i];
1216         }
1217     ffmt_str[16]='\0';
1218         return ffmt_str;
1219 }
1220
1221 #endif
1222
1223 /****************************************************************************
1224 ****************************************************************************/
1225 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1226                                   struct current_user *user, WERROR *perr)
1227 {
1228         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1229         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1230         fstring architecture;
1231         pstring new_dir;
1232         pstring old_name;
1233         pstring new_name;
1234         fstring null_pw;
1235         connection_struct *conn;
1236         NTSTATUS nt_status;
1237         int ver = 0;
1238         int i;
1239
1240         *perr = WERR_OK;
1241
1242         if (level==3)
1243                 driver=driver_abstract.info_3;
1244         else if (level==6) {
1245                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1246                 driver = &converted_driver;
1247         } else {
1248                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1249                 return False;
1250         }
1251
1252         get_short_archi(architecture, driver->environment);
1253
1254         /* connect to the print$ share under the same account as the user connected to the rpc pipe */  
1255         /* Null password is ok - we are already an authenticated user... */
1256         *null_pw = '\0';
1257         conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status);
1258
1259         if (conn == NULL) {
1260                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1261                 *perr = ntstatus_to_werror(nt_status);
1262                 return False;
1263         }
1264
1265         /*
1266          * Save who we are - we are temporarily becoming the connection user.
1267          */
1268
1269         push_sec_ctx();
1270
1271         if (!become_user(conn, conn->vuid)) {
1272                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1273                 pop_sec_ctx();
1274                 return False;
1275         }
1276
1277         /*
1278          * make the directories version and version\driver_name
1279          * under the architecture directory.
1280          */
1281         DEBUG(5,("Creating first directory\n"));
1282         slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1283         mkdir_internal(conn, new_dir);
1284
1285         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1286          * listed for this driver which has already been moved, skip it (note:
1287          * drivers may list the same file name several times. Then check if the
1288          * file already exists in archi\cversion\, if so, check that the version
1289          * info (or time stamps if version info is unavailable) is newer (or the
1290          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1291          * Otherwise, delete the file.
1292          *
1293          * If a file is not moved to archi\cversion\ because of an error, all the
1294          * rest of the 'unmoved' driver files are removed from archi\. If one or
1295          * more of the driver's files was already moved to archi\cversion\, it
1296          * potentially leaves the driver in a partially updated state. Version
1297          * trauma will most likely occur if an client attempts to use any printer
1298          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1299          * done is appropriate... later JRR
1300          */
1301
1302         DEBUG(5,("Moving files now !\n"));
1303
1304         if (driver->driverpath && strlen(driver->driverpath)) {
1305                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);      
1306                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
1307                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1308                         NTSTATUS status;
1309                         status = rename_internals(conn, new_name, old_name, True);
1310                         if (!NT_STATUS_IS_OK(status)) {
1311                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1312                                                 new_name, old_name));
1313                                 *perr = ntstatus_to_werror(status);
1314                                 unlink_internals(conn, 0, new_name);
1315                                 ver = -1;
1316                         }
1317                 }
1318                 else
1319                         unlink_internals(conn, 0, new_name);
1320         }
1321
1322         if (driver->datafile && strlen(driver->datafile)) {
1323                 if (!strequal(driver->datafile, driver->driverpath)) {
1324                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);        
1325                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
1326                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1327                                 NTSTATUS status;
1328                                 status = rename_internals(conn, new_name, old_name, True);
1329                                 if (!NT_STATUS_IS_OK(status)) {
1330                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1331                                                         new_name, old_name));
1332                                         *perr = ntstatus_to_werror(status);
1333                                         unlink_internals(conn, 0, new_name);
1334                                         ver = -1;
1335                                 }
1336                         }
1337                         else
1338                                 unlink_internals(conn, 0, new_name);
1339                 }
1340         }
1341
1342         if (driver->configfile && strlen(driver->configfile)) {
1343                 if (!strequal(driver->configfile, driver->driverpath) &&
1344                         !strequal(driver->configfile, driver->datafile)) {
1345                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);      
1346                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
1347                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1348                                 NTSTATUS status;
1349                                 status = rename_internals(conn, new_name, old_name, True);
1350                                 if (!NT_STATUS_IS_OK(status)) {
1351                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1352                                                         new_name, old_name));
1353                                         *perr = ntstatus_to_werror(status);
1354                                         unlink_internals(conn, 0, new_name);
1355                                         ver = -1;
1356                                 }
1357                         }
1358                         else
1359                                 unlink_internals(conn, 0, new_name);
1360                 }
1361         }
1362
1363         if (driver->helpfile && strlen(driver->helpfile)) {
1364                 if (!strequal(driver->helpfile, driver->driverpath) &&
1365                         !strequal(driver->helpfile, driver->datafile) &&
1366                         !strequal(driver->helpfile, driver->configfile)) {
1367                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);        
1368                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
1369                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1370                                 NTSTATUS status;
1371                                 status = rename_internals(conn, new_name, old_name, True);
1372                                 if (!NT_STATUS_IS_OK(status)) {
1373                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1374                                                         new_name, old_name));
1375                                         *perr = ntstatus_to_werror(status);
1376                                         unlink_internals(conn, 0, new_name);
1377                                         ver = -1;
1378                                 }
1379                         }
1380                         else
1381                                 unlink_internals(conn, 0, new_name);
1382                 }
1383         }
1384
1385         if (driver->dependentfiles) {
1386                 for (i=0; *driver->dependentfiles[i]; i++) {
1387                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1388                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1389                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1390                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1391                                 int j;
1392                                 for (j=0; j < i; j++) {
1393                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1394                                                 goto NextDriver;
1395                                         }
1396                                 }
1397
1398                                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);       
1399                                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
1400                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1401                                         NTSTATUS status;
1402                                         status = rename_internals(conn, new_name, old_name, True);
1403                                         if (!NT_STATUS_IS_OK(status)) {
1404                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1405                                                                 new_name, old_name));
1406                                                 *perr = ntstatus_to_werror(status);
1407                                                 unlink_internals(conn, 0, new_name);
1408                                                 ver = -1;
1409                                         }
1410                                 }
1411                                 else
1412                                         unlink_internals(conn, 0, new_name);
1413                         }
1414                 NextDriver: ;
1415                 }
1416         }
1417
1418         close_cnum(conn, user->vuid);
1419         pop_sec_ctx();
1420
1421         return ver == -1 ? False : True;
1422 }
1423
1424 /****************************************************************************
1425 ****************************************************************************/
1426 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1427 {
1428         int len, buflen;
1429         fstring architecture;
1430         pstring directory;
1431         pstring temp_name;
1432         pstring key;
1433         char *buf;
1434         int i, ret;
1435         TDB_DATA kbuf, dbuf;
1436
1437         get_short_archi(architecture, driver->environment);
1438
1439         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1440          * \\server is added in the rpc server layer.
1441          * It does make sense to NOT store the server's name in the printer TDB.
1442          */
1443
1444         slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1445
1446     /* .inf files do not always list a file for each of the four standard files. 
1447      * Don't prepend a path to a null filename, or client claims:
1448      *   "The server on which the printer resides does not have a suitable 
1449      *   <printer driver name> printer driver installed. Click OK if you 
1450      *   wish to install the driver on your local machine."
1451      */
1452         if (strlen(driver->driverpath)) {
1453         fstrcpy(temp_name, driver->driverpath);
1454         slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1455     }
1456
1457         if (strlen(driver->datafile)) {
1458         fstrcpy(temp_name, driver->datafile);
1459         slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1460     }
1461
1462         if (strlen(driver->configfile)) {
1463         fstrcpy(temp_name, driver->configfile);
1464         slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1465     }
1466
1467         if (strlen(driver->helpfile)) {
1468         fstrcpy(temp_name, driver->helpfile);
1469         slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1470     }
1471
1472         if (driver->dependentfiles) {
1473                 for (i=0; *driver->dependentfiles[i]; i++) {
1474             fstrcpy(temp_name, driver->dependentfiles[i]);
1475             slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1476                 }
1477         }
1478
1479         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1480
1481         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1482
1483         buf = NULL;
1484         len = buflen = 0;
1485
1486  again:
1487         len = 0;
1488         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1489                         driver->cversion,
1490                         driver->name,
1491                         driver->environment,
1492                         driver->driverpath,
1493                         driver->datafile,
1494                         driver->configfile,
1495                         driver->helpfile,
1496                         driver->monitorname,
1497                         driver->defaultdatatype);
1498
1499         if (driver->dependentfiles) {
1500                 for (i=0; *driver->dependentfiles[i]; i++) {
1501                         len += tdb_pack(buf+len, buflen-len, "f",
1502                                         driver->dependentfiles[i]);
1503                 }
1504         }
1505
1506         if (len != buflen) {
1507                 char *tb;
1508                 
1509                 tb = (char *)Realloc(buf, len);
1510                 if (!tb) {
1511                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1512                         ret = -1;
1513                         goto done;
1514                 }
1515                 else buf = tb;
1516                 buflen = len;
1517                 goto again;
1518         }
1519
1520
1521         kbuf.dptr = key;
1522         kbuf.dsize = strlen(key)+1;
1523         dbuf.dptr = buf;
1524         dbuf.dsize = len;
1525         
1526         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1527
1528 done:
1529         if (ret)
1530                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1531
1532         SAFE_FREE(buf);
1533         return ret;
1534 }
1535
1536 /****************************************************************************
1537 ****************************************************************************/
1538 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1539 {
1540         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1541
1542         ZERO_STRUCT(info3);
1543         info3.cversion = driver->version;
1544         fstrcpy(info3.name,driver->name);
1545         fstrcpy(info3.environment,driver->environment);
1546         fstrcpy(info3.driverpath,driver->driverpath);
1547         fstrcpy(info3.datafile,driver->datafile);
1548         fstrcpy(info3.configfile,driver->configfile);
1549         fstrcpy(info3.helpfile,driver->helpfile);
1550         fstrcpy(info3.monitorname,driver->monitorname);
1551         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1552         info3.dependentfiles = driver->dependentfiles;
1553
1554         return add_a_printer_driver_3(&info3);
1555 }
1556
1557
1558 /****************************************************************************
1559 ****************************************************************************/
1560 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1561 {
1562         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1563
1564         ZERO_STRUCT(info);
1565
1566         fstrcpy(info.name, in_prt);
1567         fstrcpy(info.defaultdatatype, "RAW");
1568         
1569         fstrcpy(info.driverpath, "");
1570         fstrcpy(info.datafile, "");
1571         fstrcpy(info.configfile, "");
1572         fstrcpy(info.helpfile, "");
1573
1574         if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1575                 return WERR_NOMEM;
1576
1577         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1578         fstrcpy(info.dependentfiles[0], "");
1579
1580         *info_ptr = memdup(&info, sizeof(info));
1581         
1582         return WERR_OK;
1583 }
1584
1585 /****************************************************************************
1586 ****************************************************************************/
1587 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1588 {
1589         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1590         TDB_DATA kbuf, dbuf;
1591         fstring architecture;
1592         int len = 0;
1593         int i;
1594         pstring key;
1595
1596         ZERO_STRUCT(driver);
1597
1598         get_short_archi(architecture, in_arch);
1599
1600         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1601
1602         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1603
1604         kbuf.dptr = key;
1605         kbuf.dsize = strlen(key)+1;
1606         
1607         dbuf = tdb_fetch(tdb_drivers, kbuf);
1608 #if 0
1609         if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1610 #else
1611         if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1612 #endif
1613         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1614                           &driver.cversion,
1615                           driver.name,
1616                           driver.environment,
1617                           driver.driverpath,
1618                           driver.datafile,
1619                           driver.configfile,
1620                           driver.helpfile,
1621                           driver.monitorname,
1622                           driver.defaultdatatype);
1623
1624         i=0;
1625         while (len < dbuf.dsize) {
1626                 fstring *tddfs;
1627         
1628                 tddfs = (fstring *)Realloc(driver.dependentfiles,
1629                                                          sizeof(fstring)*(i+2));
1630                 if (tddfs == NULL) {
1631                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1632                         break;
1633                 }
1634                 else driver.dependentfiles = tddfs;
1635
1636                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1637                                   &driver.dependentfiles[i]);
1638                 i++;
1639         }
1640         if (driver.dependentfiles != NULL)
1641                 fstrcpy(driver.dependentfiles[i], "");
1642
1643         SAFE_FREE(dbuf.dptr);
1644
1645         if (len != dbuf.dsize) {
1646                 SAFE_FREE(driver.dependentfiles);
1647
1648                 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1649         }
1650
1651         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1652
1653         return WERR_OK;
1654 }
1655
1656 /****************************************************************************
1657 ****************************************************************************/
1658 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1659 {
1660         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1661         TDB_DATA kbuf;
1662         pstring key;
1663         int i;
1664         line[0] = '\0';
1665
1666         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1667         DEBUG(10,("driver key: [%s]\n", key));
1668         
1669         kbuf.dptr = key;
1670         kbuf.dsize = strlen(key)+1;
1671         if (!tdb_exists(tdb_drivers, kbuf)) return False;
1672
1673         ZERO_STRUCT(info3);
1674         get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1675         
1676     DEBUGADD(10,("info3->name            [%s]\n", info3->name));
1677     DEBUGADD(10,("info3->datafile        [%s]\n", info3->datafile));
1678     DEBUGADD(10,("info3->helpfile        [%s]\n", info3->helpfile));
1679     DEBUGADD(10,("info3->monitorname     [%s]\n", info3->monitorname));
1680     DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1681         for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1682     DEBUGADD(10,("info3->dependentfiles  [%s]\n", info3->dependentfiles[i]));
1683     }
1684     DEBUGADD(10,("info3->environment     [%s]\n", info3->environment));
1685     DEBUGADD(10,("info3->driverpath      [%s]\n", info3->driverpath));
1686     DEBUGADD(10,("info3->configfile      [%s]\n", info3->configfile));
1687
1688         /*pstrcat(line, info3->name);             pstrcat(line, ":");*/
1689         trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1690         pstrcat(line, info3->configfile);
1691     pstrcat(line, ":");
1692         trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1693         pstrcat(line, info3->datafile);
1694     pstrcat(line, ":");
1695         trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1696         pstrcat(line, info3->helpfile);
1697     pstrcat(line, ":");
1698         trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1699         pstrcat(line, info3->monitorname);
1700     pstrcat(line, ":");
1701         pstrcat(line, "RAW");                /*info3->defaultdatatype);*/
1702     pstrcat(line, ":");
1703
1704         for (i=0; info3->dependentfiles &&
1705                  *info3->dependentfiles[i]; i++) {
1706                 if (i) pstrcat(line, ",");               /* don't end in a "," */
1707                 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1708                 pstrcat(line, info3->dependentfiles[i]);
1709         }
1710         
1711         SAFE_FREE(info3);
1712
1713         return True;    
1714 }
1715
1716 /****************************************************************************
1717 debugging function, dump at level 6 the struct in the logs
1718 ****************************************************************************/
1719 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1720 {
1721         uint32 result;
1722         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1723         int i;
1724         
1725         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1726         
1727         switch (level)
1728         {
1729                 case 3:
1730                 {
1731                         if (driver.info_3 == NULL)
1732                                 result=5;
1733                         else {
1734                                 info3=driver.info_3;
1735                         
1736                                 DEBUGADD(106,("version:[%d]\n",         info3->cversion));
1737                                 DEBUGADD(106,("name:[%s]\n",            info3->name));
1738                                 DEBUGADD(106,("environment:[%s]\n",     info3->environment));
1739                                 DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
1740                                 DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
1741                                 DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
1742                                 DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
1743                                 DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
1744                                 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1745                                 
1746                                 for (i=0; info3->dependentfiles &&
1747                                           *info3->dependentfiles[i]; i++) {
1748                                         DEBUGADD(106,("dependentfile:[%s]\n",
1749                                                       info3->dependentfiles[i]));
1750                                 }
1751                                 result=0;
1752                         }
1753                         break;
1754                 }
1755                 default:
1756                         DEBUGADD(1,("Level not implemented\n"));
1757                         result=1;
1758                         break;
1759         }
1760         
1761         return result;
1762 }
1763
1764 /****************************************************************************
1765 ****************************************************************************/
1766 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1767 {
1768         int len = 0;
1769
1770         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1771
1772         if (!nt_devmode) return len;
1773
1774         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1775                         nt_devmode->devicename,
1776                         nt_devmode->formname,
1777
1778                         nt_devmode->specversion,
1779                         nt_devmode->driverversion,
1780                         nt_devmode->size,
1781                         nt_devmode->driverextra,
1782                         nt_devmode->orientation,
1783                         nt_devmode->papersize,
1784                         nt_devmode->paperlength,
1785                         nt_devmode->paperwidth,
1786                         nt_devmode->scale,
1787                         nt_devmode->copies,
1788                         nt_devmode->defaultsource,
1789                         nt_devmode->printquality,
1790                         nt_devmode->color,
1791                         nt_devmode->duplex,
1792                         nt_devmode->yresolution,
1793                         nt_devmode->ttoption,
1794                         nt_devmode->collate,
1795                         nt_devmode->logpixels,
1796                         
1797                         nt_devmode->fields,
1798                         nt_devmode->bitsperpel,
1799                         nt_devmode->pelswidth,
1800                         nt_devmode->pelsheight,
1801                         nt_devmode->displayflags,
1802                         nt_devmode->displayfrequency,
1803                         nt_devmode->icmmethod,
1804                         nt_devmode->icmintent,
1805                         nt_devmode->mediatype,
1806                         nt_devmode->dithertype,
1807                         nt_devmode->reserved1,
1808                         nt_devmode->reserved2,
1809                         nt_devmode->panningwidth,
1810                         nt_devmode->panningheight,
1811                         nt_devmode->private);
1812
1813         
1814         if (nt_devmode->private) {
1815                 len += tdb_pack(buf+len, buflen-len, "B",
1816                                 nt_devmode->driverextra,
1817                                 nt_devmode->private);
1818         }
1819
1820         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1821
1822         return len;
1823 }
1824
1825 /****************************************************************************
1826 ****************************************************************************/
1827 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1828 {
1829         int len = 0;
1830
1831         while (param != NULL) {
1832                 len += tdb_pack(buf+len, buflen-len, "pfdB",
1833                                 param,
1834                                 param->value,
1835                                 param->type,
1836                                 param->data_len,
1837                                 param->data);
1838                 param=param->next;      
1839         }
1840
1841         len += tdb_pack(buf+len, buflen-len, "p", param);
1842
1843         return len;
1844 }
1845
1846
1847 /****************************************************************************
1848 delete a printer - this just deletes the printer info file, any open
1849 handles are not affected
1850 ****************************************************************************/
1851 uint32 del_a_printer(char *sharename)
1852 {
1853         pstring key;
1854         TDB_DATA kbuf;
1855
1856         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1857
1858         kbuf.dptr=key;
1859         kbuf.dsize=strlen(key)+1;
1860
1861         tdb_delete(tdb_printers, kbuf);
1862         return 0;
1863 }
1864
1865 /* FIXME!!!  Reorder so this forward declaration is not necessary --jerry */
1866 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1867 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1868 /****************************************************************************
1869 ****************************************************************************/
1870 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1871 {
1872         pstring key;
1873         char *buf;
1874         int buflen, len;
1875         WERROR ret;
1876         TDB_DATA kbuf, dbuf;
1877         
1878         /*
1879          * in addprinter: no servername and the printer is the name
1880          * in setprinter: servername is \\server
1881          *                and printer is \\server\\printer
1882          *
1883          * Samba manages only local printers.
1884          * we currently don't support things like path=\\other_server\printer
1885          */
1886
1887         if (info->servername[0]!='\0') {
1888                 trim_string(info->printername, info->servername, NULL);
1889                 trim_string(info->printername, "\\", NULL);
1890                 info->servername[0]='\0';
1891         }
1892
1893         /*
1894          * JFM: one day I'll forget.
1895          * below that's info->portname because that's the SAMBA sharename
1896          * and I made NT 'thinks' it's the portname
1897          * the info->sharename is the thing you can name when you add a printer
1898          * that's the short-name when you create shared printer for 95/98
1899          * So I've made a limitation in SAMBA: you can only have 1 printer model
1900          * behind a SAMBA share.
1901          */
1902
1903         buf = NULL;
1904         buflen = 0;
1905
1906  again: 
1907         len = 0;
1908         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1909                         info->attributes,
1910                         info->priority,
1911                         info->default_priority,
1912                         info->starttime,
1913                         info->untiltime,
1914                         info->status,
1915                         info->cjobs,
1916                         info->averageppm,
1917                         info->changeid,
1918                         info->c_setprinter,
1919                         info->setuptime,
1920                         info->servername,
1921                         info->printername,
1922                         info->sharename,
1923                         info->portname,
1924                         info->drivername,
1925                         info->comment,
1926                         info->location,
1927                         info->sepfile,
1928                         info->printprocessor,
1929                         info->datatype,
1930                         info->parameters);
1931
1932         len += pack_devicemode(info->devmode, buf+len, buflen-len);
1933         
1934         len += pack_specifics(info->specific, buf+len, buflen-len);
1935
1936         if (buflen != len) {
1937                 char *tb;
1938                 
1939                 tb = (char *)Realloc(buf, len);
1940                 if (!tb) {
1941                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1942                         ret = WERR_NOMEM;
1943                         goto done;
1944                 }
1945                 else buf = tb;
1946                 buflen = len;
1947                 goto again;
1948         }
1949         
1950
1951         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1952
1953         kbuf.dptr = key;
1954         kbuf.dsize = strlen(key)+1;
1955         dbuf.dptr = buf;
1956         dbuf.dsize = len;
1957
1958         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
1959
1960 done:
1961         if (!W_ERROR_IS_OK(ret))
1962                 DEBUG(8, ("error updating printer to tdb on disk\n"));
1963
1964         SAFE_FREE(buf);
1965
1966         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1967                  info->sharename, info->drivername, info->portname, len));
1968
1969         return ret;
1970 }
1971
1972
1973 /****************************************************************************
1974 ****************************************************************************/
1975 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1976 {
1977         NT_PRINTER_PARAM *current;
1978         
1979         DEBUG(108,("add_a_specific_param\n"));  
1980
1981         (*param)->next=NULL;
1982         
1983         if (info_2->specific == NULL)
1984         {
1985                 info_2->specific=*param;
1986         }
1987         else
1988         {
1989                 current=info_2->specific;               
1990                 while (current->next != NULL) {
1991                         current=current->next;
1992                 }               
1993                 current->next=*param;
1994         }
1995
1996         *param = NULL;
1997 }
1998
1999 /****************************************************************************
2000 ****************************************************************************/
2001 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2002 {
2003         NT_PRINTER_PARAM *current;
2004         NT_PRINTER_PARAM *previous;
2005         
2006         current=info_2->specific;
2007         previous=current;
2008         
2009         if (current==NULL) return (False);
2010         
2011         if ( !strcmp(current->value, param->value) &&
2012             (strlen(current->value)==strlen(param->value)) ) {
2013                 DEBUG(109,("deleting first value\n"));
2014                 info_2->specific=current->next;
2015                 SAFE_FREE(current->data);
2016                 SAFE_FREE(current);
2017                 DEBUG(109,("deleted first value\n"));
2018                 return (True);
2019         }
2020
2021         current=previous->next;
2022                 
2023         while ( current!=NULL ) {
2024                 if (!strcmp(current->value, param->value) &&
2025                     strlen(current->value)==strlen(param->value) ) {
2026                         DEBUG(109,("deleting current value\n"));
2027                         previous->next=current->next;
2028                         SAFE_FREE(current->data);
2029                         SAFE_FREE(current);
2030                         DEBUG(109,("deleted current value\n"));
2031                         return(True);
2032                 }
2033                 
2034                 previous=previous->next;
2035                 current=current->next;
2036         }
2037         return (False);
2038 }
2039
2040 /****************************************************************************
2041  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2042 ****************************************************************************/
2043 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2044 {
2045         NT_PRINTER_PARAM *param = *param_ptr;
2046
2047         if(param == NULL)
2048                 return;
2049
2050         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2051
2052         SAFE_FREE(param->data);
2053         SAFE_FREE(*param_ptr);
2054 }
2055
2056 /****************************************************************************
2057  Malloc and return an NT devicemode.
2058 ****************************************************************************/
2059
2060 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2061 {
2062 /*
2063  * should I init this ones ???
2064         nt_devmode->devicename
2065 */
2066
2067         char adevice[32];
2068         NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2069
2070         if (nt_devmode == NULL) {
2071                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2072                 return NULL;
2073         }
2074
2075         ZERO_STRUCTP(nt_devmode);
2076
2077         safe_strcpy(adevice, default_devicename, sizeof(adevice));
2078         fstrcpy(nt_devmode->devicename, adevice);       
2079         
2080         fstrcpy(nt_devmode->formname, "Letter");
2081
2082         nt_devmode->specversion      = 0x0401;
2083         nt_devmode->driverversion    = 0x0400;
2084         nt_devmode->size             = 0x00DC;
2085         nt_devmode->driverextra      = 0x0000;
2086         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2087                                        DEFAULTSOURCE | COPIES | SCALE |
2088                                        PAPERSIZE | ORIENTATION;
2089         nt_devmode->orientation      = 1;
2090         nt_devmode->papersize        = PAPER_LETTER;
2091         nt_devmode->paperlength      = 0;
2092         nt_devmode->paperwidth       = 0;
2093         nt_devmode->scale            = 0x64;
2094         nt_devmode->copies           = 01;
2095         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2096         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2097         nt_devmode->color            = COLOR_MONOCHROME;
2098         nt_devmode->duplex           = DUP_SIMPLEX;
2099         nt_devmode->yresolution      = 0;
2100         nt_devmode->ttoption         = TT_SUBDEV;
2101         nt_devmode->collate          = COLLATE_FALSE;
2102         nt_devmode->icmmethod        = 0;
2103         nt_devmode->icmintent        = 0;
2104         nt_devmode->mediatype        = 0;
2105         nt_devmode->dithertype       = 0;
2106
2107         /* non utilisés par un driver d'imprimante */
2108         nt_devmode->logpixels        = 0;
2109         nt_devmode->bitsperpel       = 0;
2110         nt_devmode->pelswidth        = 0;
2111         nt_devmode->pelsheight       = 0;
2112         nt_devmode->displayflags     = 0;
2113         nt_devmode->displayfrequency = 0;
2114         nt_devmode->reserved1        = 0;
2115         nt_devmode->reserved2        = 0;
2116         nt_devmode->panningwidth     = 0;
2117         nt_devmode->panningheight    = 0;
2118         
2119         nt_devmode->private = NULL;
2120         return nt_devmode;
2121 }
2122
2123 /****************************************************************************
2124  Deepcopy an NT devicemode.
2125 ****************************************************************************/
2126
2127 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2128 {
2129         NT_DEVICEMODE *new_nt_devicemode = NULL;
2130
2131         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2132                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2133                 return NULL;
2134         }
2135
2136         new_nt_devicemode->private = NULL;
2137         if (nt_devicemode->private != NULL) {
2138                 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2139                         SAFE_FREE(new_nt_devicemode);
2140                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2141                         return NULL;
2142         }
2143         }
2144
2145         return new_nt_devicemode;
2146 }
2147
2148 /****************************************************************************
2149  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2150 ****************************************************************************/
2151
2152 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2153 {
2154         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2155
2156         if(nt_devmode == NULL)
2157                 return;
2158
2159         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2160
2161         SAFE_FREE(nt_devmode->private);
2162         SAFE_FREE(*devmode_ptr);
2163 }
2164
2165 /****************************************************************************
2166  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2167 ****************************************************************************/
2168 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2169 {
2170         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2171         NT_PRINTER_PARAM *param_ptr;
2172
2173         if(info == NULL)
2174                 return;
2175
2176         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2177
2178         free_nt_devicemode(&info->devmode);
2179
2180         for(param_ptr = info->specific; param_ptr; ) {
2181                 NT_PRINTER_PARAM *tofree = param_ptr;
2182
2183                 param_ptr = param_ptr->next;
2184                 free_nt_printer_param(&tofree);
2185         }
2186
2187         SAFE_FREE(*info_ptr);
2188 }
2189
2190
2191 /****************************************************************************
2192 ****************************************************************************/
2193 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2194 {
2195         int len = 0;
2196         int extra_len = 0;
2197         NT_DEVICEMODE devmode;
2198
2199         ZERO_STRUCT(devmode);
2200
2201         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2202
2203         if (!*nt_devmode) return len;
2204
2205         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2206                           devmode.devicename,
2207                           devmode.formname,
2208
2209                           &devmode.specversion,
2210                           &devmode.driverversion,
2211                           &devmode.size,
2212                           &devmode.driverextra,
2213                           &devmode.orientation,
2214                           &devmode.papersize,
2215                           &devmode.paperlength,
2216                           &devmode.paperwidth,
2217                           &devmode.scale,
2218                           &devmode.copies,
2219                           &devmode.defaultsource,
2220                           &devmode.printquality,
2221                           &devmode.color,
2222                           &devmode.duplex,
2223                           &devmode.yresolution,
2224                           &devmode.ttoption,
2225                           &devmode.collate,
2226                           &devmode.logpixels,
2227                         
2228                           &devmode.fields,
2229                           &devmode.bitsperpel,
2230                           &devmode.pelswidth,
2231                           &devmode.pelsheight,
2232                           &devmode.displayflags,
2233                           &devmode.displayfrequency,
2234                           &devmode.icmmethod,
2235                           &devmode.icmintent,
2236                           &devmode.mediatype,
2237                           &devmode.dithertype,
2238                           &devmode.reserved1,
2239                           &devmode.reserved2,
2240                           &devmode.panningwidth,
2241                           &devmode.panningheight,
2242                           &devmode.private);
2243         
2244         if (devmode.private) {
2245                 /* the len in tdb_unpack is an int value and
2246                  * devmode.driverextra is only a short
2247                  */
2248                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2249                 devmode.driverextra=(uint16)extra_len;
2250                 
2251                 /* check to catch an invalid TDB entry so we don't segfault */
2252                 if (devmode.driverextra == 0) {
2253                         devmode.private = NULL;
2254                 }
2255         }
2256
2257         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2258
2259         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2260         if (devmode.private)
2261                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2262
2263         return len;
2264 }
2265
2266 /****************************************************************************
2267 ****************************************************************************/
2268 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2269 {
2270         int len = 0;
2271         NT_PRINTER_PARAM param, *p;
2272
2273         *list = NULL;
2274
2275         while (1) {
2276                 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2277                 if (!p) break;
2278
2279                 len += tdb_unpack(buf+len, buflen-len, "fdB",
2280                                   param.value,
2281                                   &param.type,
2282                                   &param.data_len,
2283                                   &param.data);
2284                 param.next = *list;
2285                 *list = memdup(&param, sizeof(param));
2286
2287                 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2288         }
2289
2290         return len;
2291 }
2292
2293 static void map_to_os2_driver(fstring drivername)
2294 {
2295         static BOOL initialised=False;
2296         static fstring last_from,last_to;
2297         char *mapfile = lp_os2_driver_map();
2298         char **lines = NULL;
2299         int numlines = 0;
2300         int i;
2301
2302         if (!strlen(drivername))
2303                 return;
2304
2305         if (!*mapfile)
2306                 return;
2307
2308         if (!initialised) {
2309                 *last_from = *last_to = 0;
2310                 initialised = True;
2311         }
2312
2313         if (strequal(drivername,last_from)) {
2314                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2315                 fstrcpy(drivername,last_to);
2316                 return;
2317         }
2318
2319         lines = file_lines_load(mapfile, &numlines);
2320         if (numlines == 0) {
2321                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2322                 return;
2323         }
2324
2325         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2326
2327         for( i = 0; i < numlines; i++) {
2328                 char *nt_name = lines[i];
2329                 char *os2_name = strchr(nt_name,'=');
2330
2331                 if (!os2_name)
2332                         continue;
2333
2334                 *os2_name++ = 0;
2335
2336                 while (isspace(*nt_name))
2337                         nt_name++;
2338
2339                 if (!*nt_name || strchr("#;",*nt_name))
2340                         continue;
2341
2342                 {
2343                         int l = strlen(nt_name);
2344                         while (l && isspace(nt_name[l-1])) {
2345                                 nt_name[l-1] = 0;
2346                                 l--;
2347                         }
2348                 }
2349
2350                 while (isspace(*os2_name))
2351                         os2_name++;
2352
2353                 {
2354                         int l = strlen(os2_name);
2355                         while (l && isspace(os2_name[l-1])) {
2356                                 os2_name[l-1] = 0;
2357                                 l--;
2358                         }
2359                 }
2360
2361                 if (strequal(nt_name,drivername)) {
2362                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2363                         fstrcpy(last_from,drivername);
2364                         fstrcpy(last_to,os2_name);
2365                         fstrcpy(drivername,os2_name);
2366                         file_lines_free(lines);
2367                         return;
2368                 }
2369         }
2370
2371         file_lines_free(lines);
2372 }
2373
2374 /****************************************************************************
2375 get a default printer info 2 struct
2376 ****************************************************************************/
2377 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2378 {
2379         extern pstring global_myname;
2380         int snum;
2381         NT_PRINTER_INFO_LEVEL_2 info;
2382
2383         ZERO_STRUCT(info);
2384
2385         snum = lp_servicenumber(sharename);
2386
2387         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2388         slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
2389                  global_myname, sharename);
2390         fstrcpy(info.sharename, sharename);
2391         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2392         fstrcpy(info.drivername, lp_printerdriver(snum));
2393
2394 #if 0   /* JERRY */
2395         if (!*info.drivername)
2396                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2397 #else
2398         /* by setting the driver name to an empty string, a local NT admin
2399            can now run the **local** APW to install a local printer driver
2400            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
2401            installed on the Samba server for NT clients --jerry */
2402         if (!*info.drivername)
2403                 fstrcpy(info.drivername, "");
2404 #endif
2405
2406
2407         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2408
2409         pstrcpy(info.comment, "");
2410         fstrcpy(info.printprocessor, "winprint");
2411         fstrcpy(info.datatype, "RAW");
2412
2413         info.attributes = PRINTER_ATTRIBUTE_SHARED   \
2414                          | PRINTER_ATTRIBUTE_LOCAL  \
2415                          | PRINTER_ATTRIBUTE_RAW_ONLY \
2416                          | PRINTER_ATTRIBUTE_QUEUED ;            /* attributes */
2417
2418         info.starttime = 0; /* Minutes since 12:00am GMT */
2419         info.untiltime = 0; /* Minutes since 12:00am GMT */
2420         info.priority = 1;
2421         info.default_priority = 1;
2422         info.setuptime = (uint32)time(NULL);
2423
2424 #if 1 /* JRA - NO NOT CHANGE ! */
2425         info.devmode = NULL;
2426 #else
2427         /*
2428          * We should not return a default devicemode, as this causes
2429          * Win2K to not send the correct one on PCL drivers. It needs to
2430          * see a null devicemode so it can then overwrite the devicemode
2431          * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2432          */
2433         if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2434                 goto fail;
2435 #endif
2436
2437         /* This will get the current RPC talloc context, but we should be
2438            passing this as a parameter... fixme... JRA ! */
2439
2440         if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2441                 goto fail;
2442
2443         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2444         if (! *info_ptr) {
2445                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2446                 goto fail;
2447         }
2448
2449         return WERR_OK;
2450
2451   fail:
2452
2453         if (info.devmode)
2454                 free_nt_devicemode(&info.devmode);
2455         return WERR_ACCESS_DENIED;
2456 }
2457
2458 /****************************************************************************
2459 ****************************************************************************/
2460 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2461 {
2462         pstring key;
2463         NT_PRINTER_INFO_LEVEL_2 info;
2464         int len = 0;
2465         TDB_DATA kbuf, dbuf;
2466         fstring printername;
2467                 
2468         ZERO_STRUCT(info);
2469
2470         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2471
2472         kbuf.dptr = key;
2473         kbuf.dsize = strlen(key)+1;
2474
2475         dbuf = tdb_fetch(tdb_printers, kbuf);
2476         if (!dbuf.dptr)
2477                 return get_a_printer_2_default(info_ptr, sharename);
2478
2479         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2480                         &info.attributes,
2481                         &info.priority,
2482                         &info.default_priority,
2483                         &info.starttime,
2484                         &info.untiltime,
2485                         &info.status,
2486                         &info.cjobs,
2487                         &info.averageppm,
2488                         &info.changeid,
2489                         &info.c_setprinter,
2490                         &info.setuptime,
2491                         info.servername,
2492                         info.printername,
2493                         info.sharename,
2494                         info.portname,
2495                         info.drivername,
2496                         info.comment,
2497                         info.location,
2498                         info.sepfile,
2499                         info.printprocessor,
2500                         info.datatype,
2501                         info.parameters);
2502
2503         /* Samba has to have shared raw drivers. */
2504         info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2505
2506         /* Restore the stripped strings. */
2507         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2508         slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2509                         info.printername);
2510         fstrcpy(info.printername, printername);
2511
2512         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2513         len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2514
2515         /* This will get the current RPC talloc context, but we should be
2516        passing this as a parameter... fixme... JRA ! */
2517
2518         nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2519
2520         /* Fix for OS/2 drivers. */
2521
2522         if (get_remote_arch() == RA_OS2)
2523                 map_to_os2_driver(info.drivername);
2524
2525         SAFE_FREE(dbuf.dptr);
2526         *info_ptr=memdup(&info, sizeof(info));
2527
2528         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2529                  sharename, info.printername, info.drivername));
2530
2531         return WERR_OK; 
2532 }
2533
2534 /****************************************************************************
2535 debugging function, dump at level 6 the struct in the logs
2536 ****************************************************************************/
2537 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2538 {
2539         uint32 result;
2540         NT_PRINTER_INFO_LEVEL_2 *info2;
2541         
2542         DEBUG(106,("Dumping printer at level [%d]\n", level));
2543         
2544         switch (level)
2545         {
2546                 case 2:
2547                 {
2548                         if (printer.info_2 == NULL)
2549                                 result=5;
2550                         else
2551                         {
2552                                 info2=printer.info_2;
2553                         
2554                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2555                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2556                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2557                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2558                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2559                                 DEBUGADD(106,("status:[%s]\n", werror_str(info2->status)));
2560                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2561                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2562                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2563                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2564                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2565
2566                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2567                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2568                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2569                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2570                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2571                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2572                                 DEBUGADD(106,("location:[%s]\n", info2->location));
2573                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2574                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2575                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2576                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2577                                 result=0;
2578                         }
2579                         break;
2580                 }
2581                 default:
2582                         DEBUGADD(1,("Level not implemented\n"));
2583                         result=1;
2584                         break;
2585         }
2586         
2587         return result;
2588 }
2589
2590 /****************************************************************************
2591  Get the parameters we can substitute in an NT print job.
2592 ****************************************************************************/
2593
2594 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2595 {
2596         NT_PRINTER_INFO_LEVEL *printer = NULL;
2597         
2598         **printername = **sharename = **portname = '\0';
2599
2600         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2601                 return;
2602
2603         fstrcpy(*printername, printer->info_2->printername);
2604         fstrcpy(*sharename, printer->info_2->sharename);
2605         fstrcpy(*portname, printer->info_2->portname);
2606
2607         free_a_printer(&printer, 2);
2608 }
2609
2610 /*
2611  * The function below are the high level ones.
2612  * only those ones must be called from the spoolss code.
2613  * JFM.
2614  */
2615
2616 /****************************************************************************
2617  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2618 ****************************************************************************/
2619
2620 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2621 {
2622         WERROR result;
2623         
2624         dump_a_printer(printer, level); 
2625         
2626         switch (level)
2627         {
2628                 case 2:
2629                 {
2630                         printer.info_2->c_setprinter++;
2631                         result=update_a_printer_2(printer.info_2);
2632                         break;
2633                 }
2634                 default:
2635                         result=WERR_UNKNOWN_LEVEL;
2636                         break;
2637         }
2638         
2639         return result;
2640 }
2641
2642 /****************************************************************************
2643  Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2644  We split this out from mod_a_printer as it updates the id's and timestamps.
2645 ****************************************************************************/
2646
2647 WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2648 {
2649         WERROR result;
2650         
2651         dump_a_printer(printer, level); 
2652         
2653         switch (level)
2654         {
2655                 case 2:
2656                 {
2657                         /*
2658                          * Update the changestamp.
2659                          * Note we must *not* do this in mod_a_printer().
2660                          */
2661                         NTTIME time_nt;
2662                         time_t time_unix = time(NULL);
2663                         unix_to_nt_time(&time_nt, time_unix);
2664                         if (printer.info_2->changeid==time_nt.low)
2665                                 printer.info_2->changeid++;
2666                         else
2667                                 printer.info_2->changeid=time_nt.low;
2668
2669                         printer.info_2->c_setprinter++;
2670
2671                         result=update_a_printer_2(printer.info_2);
2672                         break;
2673                 }
2674                 default:
2675                         result=WERR_UNKNOWN_LEVEL;
2676                         break;
2677         }
2678         
2679         return result;
2680 }
2681
2682 /****************************************************************************
2683  Initialize printer devmode & data with previously saved driver init values.
2684 ****************************************************************************/
2685 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2686 {
2687         int                     len = 0;
2688         pstring                 key;
2689         TDB_DATA                kbuf, dbuf;
2690         NT_PRINTER_PARAM        *current;
2691         NT_PRINTER_INFO_LEVEL_2 info;
2692
2693         ZERO_STRUCT(info);
2694
2695         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2696
2697         kbuf.dptr = key;
2698         kbuf.dsize = strlen(key)+1;
2699
2700         dbuf = tdb_fetch(tdb_drivers, kbuf);
2701         if (!dbuf.dptr)
2702                 return False;
2703
2704         /*
2705          * Get the saved DEVMODE..
2706          */
2707         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2708
2709         /*
2710          * The saved DEVMODE contains the devicename from the printer used during
2711          * the initialization save. Change it to reflect the new printer.
2712          */
2713         ZERO_STRUCT(info.devmode->devicename);
2714         fstrcpy(info.devmode->devicename, info_ptr->printername);
2715
2716         /* 
2717          *      Bind the saved DEVMODE to the new the printer.
2718          */
2719         free_nt_devicemode(&info_ptr->devmode);
2720         info_ptr->devmode = info.devmode;
2721
2722         DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2723                         info_ptr->printername, info_ptr->drivername));
2724
2725         /* 
2726          * There should not be any printer data 'specifics' already set during the
2727          * add printer operation, if there are delete them. 
2728          */
2729         while ( (current=info_ptr->specific) != NULL ) {
2730                 info_ptr->specific=current->next;
2731                 SAFE_FREE(current->data);
2732                 SAFE_FREE(current);
2733         }
2734
2735         /* 
2736          * Add the printer data 'specifics' to the new printer
2737          */
2738         len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2739
2740         SAFE_FREE(dbuf.dptr);
2741
2742         return True;    
2743 }
2744
2745 /****************************************************************************
2746  Initialize printer devmode & data with previously saved driver init values.
2747  When a printer is created using AddPrinter, the drivername bound to the
2748  printer is used to lookup previously saved driver initialization info, which
2749  is bound to the new printer.
2750 ****************************************************************************/
2751
2752 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2753 {
2754         uint32 result;
2755         
2756         switch (level)
2757         {
2758                 case 2:
2759                 {
2760                         result=set_driver_init_2(printer->info_2);
2761                         break;
2762                 }
2763                 default:
2764                         result=1;
2765                         break;
2766         }
2767         
2768         return result;
2769 }
2770
2771 /****************************************************************************
2772  Pack up the DEVMODE and specifics for a printer into a 'driver init' entry 
2773  in the tdb. Note: this is different from the driver entry and the printer
2774  entry. There should be a single driver init entry for each driver regardless
2775  of whether it was installed from NT or 2K. Technically, they should be
2776  different, but they work out to the same struct.
2777 ****************************************************************************/
2778 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2779 {
2780         pstring key;
2781         char *buf;
2782         int buflen, len, ret;
2783         TDB_DATA kbuf, dbuf;
2784
2785         buf = NULL;
2786         buflen = 0;
2787
2788  again: 
2789         len = 0;
2790         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2791
2792         len += pack_specifics(info->specific, buf+len, buflen-len);
2793
2794         if (buflen != len) {
2795                 char *tb;
2796                 
2797                 tb = (char *)Realloc(buf, len);
2798                 if (!tb) {
2799                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2800                         ret = -1;
2801                         goto done;
2802                 }
2803                 else buf = tb;
2804                 buflen = len;
2805                 goto again;
2806         }
2807
2808         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2809
2810         kbuf.dptr = key;
2811         kbuf.dsize = strlen(key)+1;
2812         dbuf.dptr = buf;
2813         dbuf.dsize = len;
2814
2815         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2816
2817 done:
2818         if (ret == -1)
2819                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2820
2821         SAFE_FREE(buf);
2822
2823         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2824                  info->sharename, info->drivername));
2825
2826         return ret;
2827 }
2828
2829 /****************************************************************************
2830  Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2831 ****************************************************************************/
2832
2833 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2834 {
2835         uint32 result;
2836         
2837         dump_a_printer(printer, level); 
2838         
2839         switch (level)
2840         {
2841                 case 2:
2842                 {
2843                         result=update_driver_init_2(printer.info_2);
2844                         break;
2845                 }
2846                 default:
2847                         result=1;
2848                         break;
2849         }
2850         
2851         return result;
2852 }
2853
2854 /****************************************************************************
2855  Convert the printer data value, a REG_BINARY array, into an initialization 
2856  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2857  got to keep the endians happy :).
2858 ****************************************************************************/
2859
2860 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2861 {
2862         BOOL       result = False;
2863         prs_struct ps;
2864         DEVICEMODE devmode;
2865
2866         ZERO_STRUCT(devmode);
2867
2868         prs_init(&ps, 0, ctx, UNMARSHALL);
2869         ps.data_p      = (char *)param->data;
2870         ps.buffer_size = param->data_len;
2871
2872         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2873                 result = convert_devicemode("", &devmode, &nt_devmode);
2874         else
2875                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2876
2877         return result;
2878 }
2879
2880 /****************************************************************************
2881  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2882
2883  1. Use the driver's config DLL to this UNC printername and:
2884     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2885     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2886  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2887
2888  The last step triggers saving the "driver initialization" information for
2889  this printer into the tdb. Later, new printers that use this driver will
2890  have this initialization information bound to them. This simulates the
2891  driver initialization, as if it had run on the Samba server (as it would
2892  have done on NT).
2893
2894  The Win32 client side code requirement sucks! But until we can run arbitrary
2895  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2896  
2897  It would have been easier to use SetPrinter because all the UNMARSHALLING of
2898  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2899  about it and you will realize why.  JRR 010720
2900 ****************************************************************************/
2901
2902 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2903 {
2904         WERROR        status       = WERR_OK;
2905         TALLOC_CTX    *ctx         = NULL;
2906         NT_DEVICEMODE *nt_devmode  = NULL;
2907         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2908         
2909         /*
2910          * Set devmode on printer info, so entire printer initialization can be 
2911          * saved to tdb.
2912          */
2913         if ((ctx = talloc_init()) == NULL)
2914                 return WERR_NOMEM;
2915
2916         if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2917                 status = WERR_NOMEM;
2918                 goto done;
2919         }
2920         
2921         ZERO_STRUCTP(nt_devmode);
2922
2923         /*
2924          * The DEVMODE is held in the 'data' component of the param in raw binary.
2925          * Convert it to to a devmode structure
2926          */
2927         if (!convert_driver_init(param, ctx, nt_devmode)) {
2928                 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
2929                 status = WERR_INVALID_PARAM;
2930                 goto done;
2931         }
2932
2933         /*
2934          * Pack up and add (or update) the DEVMODE and any current printer data to
2935          * a 'driver init' element in the tdb
2936          * 
2937          */
2938         printer->info_2->devmode = nt_devmode;
2939         if (update_driver_init(*printer, 2)!=0) {
2940                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
2941                 status = WERR_NOMEM;
2942                 goto done;
2943         }
2944         
2945         /*
2946          * If driver initialization info was successfully saved, set the current 
2947          * printer to match it. This allows initialization of the current printer 
2948          * as well as the driver.
2949          */
2950         status = mod_a_printer(*printer, 2);
2951         if (!W_ERROR_IS_OK(status)) {
2952                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
2953                                   printer->info_2->printername));
2954         }
2955
2956   done:
2957         talloc_destroy(ctx);
2958         if (nt_devmode)
2959                 SAFE_FREE(nt_devmode->private);
2960         SAFE_FREE(nt_devmode);
2961         printer->info_2->devmode = tmp_devmode;
2962
2963         return status;
2964 }
2965
2966 /****************************************************************************
2967  Update the driver init info (DEVMODE and specifics) for a printer
2968 ****************************************************************************/
2969
2970 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
2971 {
2972         WERROR status = WERR_OK;
2973         
2974         switch (level)
2975         {
2976                 case 2:
2977                 {
2978                         status=save_driver_init_2(printer, param);
2979                         break;
2980                 }
2981                 default:
2982                         status=WERR_UNKNOWN_LEVEL;
2983                         break;
2984         }
2985         
2986         return status;
2987 }
2988
2989 /****************************************************************************
2990  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2991 ****************************************************************************/
2992
2993 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2994 {
2995         WERROR result;
2996         NT_PRINTER_INFO_LEVEL *printer = NULL;
2997         
2998         *pp_printer = NULL;
2999
3000         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3001
3002         switch (level)
3003         {
3004                 case 2:
3005                 {
3006                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3007                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
3008                                 return WERR_NOMEM;
3009                         }
3010                         ZERO_STRUCTP(printer);
3011                         result=get_a_printer_2(&printer->info_2, sharename);
3012                         if (W_ERROR_IS_OK(result)) {
3013                                 dump_a_printer(*printer, level);
3014                                 *pp_printer = printer;
3015                         } else {
3016                                 SAFE_FREE(printer);
3017                         }
3018                         break;
3019                 }
3020                 default:
3021                         result=WERR_UNKNOWN_LEVEL;
3022                         break;
3023         }
3024         
3025         DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, werror_str(result)));
3026
3027         return result;
3028 }
3029
3030 /****************************************************************************
3031  Deletes a NT_PRINTER_INFO_LEVEL struct.
3032 ****************************************************************************/
3033
3034 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3035 {
3036         uint32 result;
3037         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3038
3039         DEBUG(104,("freeing a printer at level [%d]\n", level));
3040
3041         if (printer == NULL)
3042                 return 0;
3043         
3044         switch (level)
3045         {
3046                 case 2:
3047                 {
3048                         if (printer->info_2 != NULL)
3049                         {
3050                                 free_nt_printer_info_level_2(&printer->info_2);
3051                                 result=0;
3052                         }
3053                         else
3054                         {
3055                                 result=4;
3056                         }
3057                         break;
3058                 }
3059                 default:
3060                         result=1;
3061                         break;
3062         }
3063
3064         SAFE_FREE(*pp_printer);
3065         return result;
3066 }
3067
3068 /****************************************************************************
3069 ****************************************************************************/
3070 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3071 {
3072         uint32 result;
3073         DEBUG(104,("adding a printer at level [%d]\n", level));
3074         dump_a_printer_driver(driver, level);
3075         
3076         switch (level)
3077         {
3078                 case 3:
3079                 {
3080                         result=add_a_printer_driver_3(driver.info_3);
3081                         break;
3082                 }
3083
3084                 case 6:
3085                 {
3086                         result=add_a_printer_driver_6(driver.info_6);
3087                         break;
3088                 }
3089                 default:
3090                         result=1;
3091                         break;
3092         }
3093         
3094         return result;
3095 }
3096 /****************************************************************************
3097 ****************************************************************************/
3098 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3099                             fstring printername, fstring architecture, uint32 version)
3100 {
3101         WERROR result;
3102         
3103         switch (level)
3104         {
3105                 case 3:
3106                 {
3107                         result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3108                         break;
3109                 }
3110                 default:
3111                         result=W_ERROR(1);
3112                         break;
3113         }
3114         
3115         if (W_ERROR_IS_OK(result))
3116                 dump_a_printer_driver(*driver, level);
3117         return result;
3118 }
3119
3120 /****************************************************************************
3121 ****************************************************************************/
3122 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3123 {
3124         uint32 result;
3125         
3126         switch (level)
3127         {
3128                 case 3:
3129                 {
3130                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3131                         if (driver.info_3 != NULL)
3132                         {
3133                                 info3=driver.info_3;
3134                                 SAFE_FREE(info3->dependentfiles);
3135                                 ZERO_STRUCTP(info3);
3136                                 SAFE_FREE(info3);
3137                                 result=0;
3138                         }
3139                         else
3140                         {
3141                                 result=4;
3142                         }
3143                         break;
3144                 }
3145                 case 6:
3146                 {
3147                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3148                         if (driver.info_6 != NULL)
3149                         {
3150                                 info6=driver.info_6;
3151                                 SAFE_FREE(info6->dependentfiles);
3152                                 SAFE_FREE(info6->previousnames);
3153                                 ZERO_STRUCTP(info6);
3154                                 SAFE_FREE(info6);
3155                                 result=0;
3156                         }
3157                         else
3158                         {
3159                                 result=4;
3160                         }
3161                         break;
3162                 }
3163                 default:
3164                         result=1;
3165                         break;
3166         }
3167         return result;
3168 }
3169
3170
3171 /****************************************************************************
3172   Determine whether or not a particular driver is currently assigned
3173   to a printer
3174 ****************************************************************************/
3175 BOOL printer_driver_in_use (char *arch, char *driver)
3176 {
3177         TDB_DATA kbuf, newkey, dbuf;
3178         NT_PRINTER_INFO_LEVEL_2 info;
3179         int ret;
3180
3181         if (!tdb_printers)
3182                 if (!nt_printing_init())
3183                         return False;
3184
3185         DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3186         
3187         /* loop through the printers.tdb and check for the drivername */
3188         for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3189              newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
3190         {
3191
3192                 dbuf = tdb_fetch(tdb_printers, kbuf);
3193                 if (!dbuf.dptr) 
3194                         continue;
3195
3196                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0) 
3197                         continue;
3198
3199                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3200                         &info.attributes,
3201                         &info.priority,
3202                         &info.default_priority,
3203                         &info.starttime,
3204                         &info.untiltime,
3205                         &info.status,
3206                         &info.cjobs,
3207                         &info.averageppm,
3208                         &info.changeid,
3209                         &info.c_setprinter,
3210                         &info.setuptime,
3211                         info.servername,
3212                         info.printername,
3213                         info.sharename,
3214                         info.portname,
3215                         info.drivername,
3216                         info.comment,
3217                         info.location,
3218                         info.sepfile,
3219                         info.printprocessor,
3220                         info.datatype,
3221                         info.parameters);
3222
3223                 SAFE_FREE(dbuf.dptr);
3224
3225                 if (ret == -1) {
3226                         DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3227                                         info.printername));
3228                         continue;
3229                 }
3230                 
3231                 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3232                         info.printername, info.drivername));
3233                         
3234                 if (strcmp(info.drivername, driver) == 0) 
3235                 {
3236                         DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3237                                 info.printername, driver));
3238                         return True;
3239                 }       
3240         }
3241         DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3242         
3243         
3244         
3245         /* report that the driver is in use by default */
3246         return False;
3247 }
3248
3249 /****************************************************************************
3250  Remove a printer driver from the TDB.  This assumes that the the driver was
3251  previously looked up.
3252  ***************************************************************************/
3253 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3254 {
3255         pstring         key;
3256         fstring         arch;
3257         TDB_DATA        kbuf;
3258
3259
3260         get_short_archi(arch, i->environment);
3261         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3262                 arch, i->cversion, i->name); 
3263         DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3264
3265         kbuf.dptr=key;
3266         kbuf.dsize=strlen(key)+1;
3267
3268         if (tdb_delete(tdb_drivers, kbuf) == -1) {
3269                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3270                 return WERR_ACCESS_DENIED;
3271         }
3272         
3273         DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3274                 i->name));
3275         
3276         return WERR_OK;
3277 }
3278 /****************************************************************************
3279 ****************************************************************************/
3280 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3281                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
3282 {
3283         /* right now that's enough ! */ 
3284         NT_PRINTER_PARAM *param;
3285         int i=0;
3286         
3287         param=printer.info_2->specific;
3288         
3289         while (param != NULL && i < param_index) {
3290                 param=param->next;
3291                 i++;
3292         }
3293         
3294         if (param == NULL)
3295                 return False;
3296
3297         /* exited because it exist */
3298         *type=param->type;              
3299         StrnCpy(value, param->value, sizeof(fstring)-1);
3300         *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3301         if(*data == NULL)
3302                 return False;
3303         ZERO_STRUCTP(*data);
3304         memcpy(*data, param->data, param->data_len);
3305         *len=param->data_len;
3306         return True;
3307 }
3308
3309 /****************************************************************************
3310 ****************************************************************************/
3311 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3312                         fstring value, uint8 **data, uint32 *type, uint32 *len)
3313 {
3314         /* right now that's enough ! */ 
3315         NT_PRINTER_PARAM *param;
3316         
3317         DEBUG(10, ("get_specific_param\n"));
3318         
3319         param=printer.info_2->specific;
3320                 
3321         while (param != NULL)
3322         {
3323 #if 1 /* JRA - I think this should be case insensitive.... */
3324                 if ( strequal(value, param->value)
3325 #else
3326                 if ( !strcmp(value, param->value)
3327 #endif
3328                     && strlen(value)==strlen(param->value))
3329                         break;
3330                         
3331                 param=param->next;
3332         }
3333         
3334         if (param != NULL)
3335         {
3336         DEBUGADD(10, ("get_specific_param: found one param\n"));
3337                 /* exited because it exist */
3338                 *type=param->type;      
3339                 
3340                 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3341                 if(*data == NULL)
3342                         return False;
3343                 memcpy(*data, param->data, param->data_len);
3344                 *len=param->data_len;
3345
3346                 DEBUGADD(10, ("get_specific_param: exit true\n"));
3347                 return (True);
3348         }
3349         DEBUGADD(10, ("get_specific_param: exit false\n"));
3350         return (False);
3351 }
3352
3353 /****************************************************************************
3354  Store a security desc for a printer.
3355 ****************************************************************************/
3356
3357 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3358 {
3359         SEC_DESC_BUF *new_secdesc_ctr = NULL;
3360         SEC_DESC_BUF *old_secdesc_ctr = NULL;
3361         prs_struct ps;
3362         TALLOC_CTX *mem_ctx = NULL;
3363         fstring key;
3364         WERROR status;
3365
3366         mem_ctx = talloc_init();
3367         if (mem_ctx == NULL)
3368                 return WERR_NOMEM;
3369
3370         /* The old owner and group sids of the security descriptor are not
3371            present when new ACEs are added or removed by changing printer
3372            permissions through NT.  If they are NULL in the new security
3373            descriptor then copy them over from the old one. */
3374
3375         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3376                 DOM_SID *owner_sid, *group_sid;
3377                 SEC_ACL *dacl, *sacl;
3378                 SEC_DESC *psd = NULL;
3379                 size_t size;
3380
3381                 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3382
3383                 /* Pick out correct owner and group sids */
3384
3385                 owner_sid = secdesc_ctr->sec->owner_sid ?
3386                         secdesc_ctr->sec->owner_sid :
3387                         old_secdesc_ctr->sec->owner_sid;
3388
3389                 group_sid = secdesc_ctr->sec->grp_sid ?
3390                         secdesc_ctr->sec->grp_sid :
3391                         old_secdesc_ctr->sec->grp_sid;
3392
3393                 dacl = secdesc_ctr->sec->dacl ?
3394                         secdesc_ctr->sec->dacl :
3395                         old_secdesc_ctr->sec->dacl;
3396
3397                 sacl = secdesc_ctr->sec->sacl ?
3398                         secdesc_ctr->sec->sacl :
3399                         old_secdesc_ctr->sec->sacl;
3400
3401                 /* Make a deep copy of the security descriptor */
3402
3403                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3404                                     owner_sid, group_sid,
3405                                     sacl,
3406                                     dacl,
3407                                     &size);
3408
3409                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3410         }
3411
3412         if (!new_secdesc_ctr) {
3413                 new_secdesc_ctr = secdesc_ctr;
3414         }
3415
3416         /* Store the security descriptor in a tdb */
3417
3418         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3419                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3420
3421         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3422                              &ps, 1)) {
3423                 status = WERR_BADFUNC;
3424                 goto out;
3425         }
3426
3427         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3428
3429         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3430                 status = WERR_OK;
3431         } else {
3432                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3433                 status = WERR_BADFUNC;
3434         }
3435
3436         /* Free malloc'ed memory */
3437
3438  out:
3439
3440         prs_mem_free(&ps);
3441         if (mem_ctx)
3442                 talloc_destroy(mem_ctx);
3443         return status;
3444 }
3445
3446 /****************************************************************************
3447  Construct a default security descriptor buffer for a printer.
3448 ****************************************************************************/
3449
3450 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3451 {
3452         SEC_ACE ace[3];
3453         SEC_ACCESS sa;
3454         SEC_ACL *psa = NULL;
3455         SEC_DESC_BUF *sdb = NULL;
3456         SEC_DESC *psd = NULL;
3457         DOM_SID owner_sid;
3458         size_t sd_size;
3459         enum SID_NAME_USE name_type;
3460
3461         /* Create an ACE where Everyone is allowed to print */
3462
3463         init_sec_access(&sa, PRINTER_ACE_PRINT);
3464         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3465                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3466
3467         /* Make the security descriptor owned by the Administrators group
3468            on the PDC of the domain. */
3469
3470         if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3471                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3472         } else {
3473                 uint32 owner_rid;
3474
3475                 /* Backup plan - make printer owned by admins or root.
3476                    This should emulate a lanman printer as security
3477                    settings can't be changed. */
3478
3479                 sid_peek_rid(&owner_sid, &owner_rid);
3480
3481                 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3482                     owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3483                     owner_rid != DOMAIN_USER_RID_ADMIN &&
3484                     !lookup_name("root", &owner_sid, &name_type)) {
3485                         sid_copy(&owner_sid, &global_sid_World);
3486                 }
3487         }
3488
3489         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3490         init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3491                      sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3492                      SEC_ACE_FLAG_INHERIT_ONLY);
3493
3494         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3495         init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3496                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3497
3498         /* The ACL revision number in rpc_secdesc.h differs from the one
3499            created by NT when setting ACE entries in printer
3500            descriptors.  NT4 complains about the property being edited by a
3501            NT5 machine. */
3502
3503         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3504                 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3505                                     &owner_sid, NULL,
3506                                     NULL, psa, &sd_size);
3507         }
3508
3509         if (!psd) {
3510                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3511                 return NULL;
3512         }
3513
3514         sdb = make_sec_desc_buf(ctx, sd_size, psd);
3515
3516         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3517                  (unsigned int)sd_size));
3518
3519         return sdb;
3520 }
3521
3522 /****************************************************************************
3523  Get a security desc for a printer.
3524 ****************************************************************************/
3525
3526 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3527 {
3528         prs_struct ps;
3529         fstring key;
3530         char *temp;
3531
3532         if ((temp = strchr(printername + 2, '\\'))) {
3533                 printername = temp + 1;
3534         }
3535
3536         /* Fetch security descriptor from tdb */
3537
3538         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3539
3540         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3541             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3542
3543                 DEBUG(4,("using default secdesc for %s\n", printername));
3544
3545                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3546                         return False;
3547                 }
3548
3549                 return True;
3550         }
3551
3552         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3553            this security descriptor has been created when winbindd was
3554            down.  Take ownership of security descriptor. */
3555
3556         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3557                 DOM_SID owner_sid;
3558                 enum SID_NAME_USE name_type;
3559
3560                 /* Change sd owner to workgroup administrator */
3561
3562                 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3563                                         &name_type)) {
3564                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
3565                         SEC_DESC *psd = NULL;
3566                         size_t size;
3567
3568                         /* Create new sd */
3569
3570                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3571
3572                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3573                                             &owner_sid,
3574                                             (*secdesc_ctr)->sec->grp_sid,
3575                                             (*secdesc_ctr)->sec->sacl,
3576                                             (*secdesc_ctr)->sec->dacl,
3577                                             &size);
3578
3579                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3580
3581                         /* Swap with other one */
3582
3583                         *secdesc_ctr = new_secdesc_ctr;
3584
3585                         /* Set it */
3586
3587                         nt_printing_setsec(printername, *secdesc_ctr);
3588                 }
3589         }
3590
3591         if (DEBUGLEVEL >= 10) {
3592                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3593                 int i;
3594
3595                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
3596                            printername, the_acl->num_aces));
3597
3598                 for (i = 0; i < the_acl->num_aces; i++) {
3599                         fstring sid_str;
3600
3601                         sid_to_string(sid_str, &the_acl->ace[i].sid);
3602
3603                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3604                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
3605                                    the_acl->ace[i].info.mask)); 
3606                 }
3607         }
3608
3609         prs_mem_free(&ps);
3610         return True;
3611 }
3612
3613 /* error code:
3614         0: everything OK
3615         1: level not implemented
3616         2: file doesn't exist
3617         3: can't allocate memory
3618         4: can't free memory
3619         5: non existant struct
3620 */
3621
3622 /*
3623         A printer and a printer driver are 2 different things.
3624         NT manages them separatelly, Samba does the same.
3625         Why ? Simply because it's easier and it makes sense !
3626         
3627         Now explanation: You have 3 printers behind your samba server,
3628         2 of them are the same make and model (laser A and B). But laser B
3629         has an 3000 sheet feeder and laser A doesn't such an option.
3630         Your third printer is an old dot-matrix model for the accounting :-).
3631         
3632         If the /usr/local/samba/lib directory (default dir), you will have
3633         5 files to describe all of this.
3634         
3635         3 files for the printers (1 by printer):
3636                 NTprinter_laser A
3637                 NTprinter_laser B
3638                 NTprinter_accounting
3639         2 files for the drivers (1 for the laser and 1 for the dot matrix)
3640                 NTdriver_printer model X
3641                 NTdriver_printer model Y
3642
3643 jfm: I should use this comment for the text file to explain
3644         same thing for the forms BTW.
3645         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3646
3647 */
3648
3649 /* Convert generic access rights to printer object specific access rights.
3650    It turns out that NT4 security descriptors use generic access rights and
3651    NT5 the object specific ones. */
3652
3653 void map_printer_permissions(SEC_DESC *sd)
3654 {
3655         int i;
3656
3657         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3658                 se_map_generic(&sd->dacl->ace[i].info.mask,
3659                                &printer_generic_mapping);
3660         }
3661 }
3662
3663 /****************************************************************************
3664  Check a user has permissions to perform the given operation.  We use the
3665  permission constants defined in include/rpc_spoolss.h to check the various
3666  actions we perform when checking printer access.
3667
3668    PRINTER_ACCESS_ADMINISTER:
3669        print_queue_pause, print_queue_resume, update_printer_sec,
3670        update_printer, spoolss_addprinterex_level_2,
3671        _spoolss_setprinterdata
3672
3673    PRINTER_ACCESS_USE:
3674        print_job_start
3675
3676    JOB_ACCESS_ADMINISTER:
3677        print_job_delete, print_job_pause, print_job_resume,
3678        print_queue_purge
3679
3680  ****************************************************************************/
3681 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3682 {
3683         SEC_DESC_BUF *secdesc = NULL;
3684         uint32 access_granted;
3685         NTSTATUS status;
3686         BOOL result;
3687         char *pname;
3688         TALLOC_CTX *mem_ctx = NULL;
3689         extern struct current_user current_user;
3690         
3691         /* If user is NULL then use the current_user structure */
3692
3693         if (!user)
3694                 user = &current_user;
3695
3696         /* Always allow root or printer admins to do anything */
3697
3698         if (user->uid == 0 ||
3699             user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3700                 return True;
3701         }
3702
3703         /* Get printer name */
3704
3705         pname = PRINTERNAME(snum);
3706
3707         if (!pname || !*pname) {
3708                 errno = EACCES;
3709                 return False;
3710         }
3711
3712         /* Get printer security descriptor */
3713
3714         if(!(mem_ctx = talloc_init())) {
3715                 errno = ENOMEM;
3716                 return False;
3717         }
3718
3719         nt_printing_getsec(mem_ctx, pname, &secdesc);
3720
3721         if (access_type == JOB_ACCESS_ADMINISTER) {
3722                 SEC_DESC_BUF *parent_secdesc = secdesc;
3723
3724                 /* Create a child security descriptor to check permissions
3725                    against.  This is because print jobs are child objects
3726                    objects of a printer. */
3727
3728                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3729
3730                 /* Now this is the bit that really confuses me.  The access
3731                    type needs to be changed from JOB_ACCESS_ADMINISTER to
3732                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
3733                    to do with the child (job) object becoming like a
3734                    printer??  -tpot */
3735
3736                 access_type = PRINTER_ACCESS_ADMINISTER;
3737         }
3738         
3739         /* Check access */
3740         
3741         map_printer_permissions(secdesc->sec);
3742
3743         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
3744                                  &access_granted, &status);
3745
3746         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3747
3748         talloc_destroy(mem_ctx);
3749         
3750         if (!result)
3751                 errno = EACCES;
3752
3753         return result;
3754 }
3755
3756 /****************************************************************************
3757  Check the time parameters allow a print operation.
3758 *****************************************************************************/
3759
3760 BOOL print_time_access_check(int snum)
3761 {
3762         NT_PRINTER_INFO_LEVEL *printer = NULL;
3763         BOOL ok = False;
3764         time_t now = time(NULL);
3765         struct tm *t;
3766         uint32 mins;
3767
3768         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3769                 return False;
3770
3771         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3772                 ok = True;
3773
3774         t = gmtime(&now);
3775         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3776
3777         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3778                 ok = True;
3779
3780         free_a_printer(&printer, 2);
3781
3782         if (!ok)
3783                 errno = EACCES;
3784
3785         return ok;
3786 }
3787
3788 /****************************************************************************
3789  Attempt to write a default device.
3790 *****************************************************************************/
3791
3792 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3793 {
3794         NT_PRINTER_INFO_LEVEL *printer = NULL;
3795         WERROR result;
3796
3797         /*
3798          * Don't bother if no default devicemode was sent.
3799          */
3800
3801         if (printer_default->devmode_cont.devmode == NULL)
3802                 return WERR_OK;
3803
3804         result = get_a_printer(&printer, 2, lp_servicename(snum));
3805         if (!W_ERROR_IS_OK(result)) return result;
3806
3807         /*
3808          * Just ignore it if we already have a devmode.
3809          */
3810 #if 0
3811         if (printer->info_2->devmode != NULL)
3812                 goto done;
3813 #endif
3814         /*
3815          * We don't have a devicemode and we're trying to write
3816          * one. Check we have the access needed.
3817          */
3818         DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3819
3820         if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) != 
3821               PRINTER_ACCESS_ADMINISTER) {
3822                 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3823                 result = WERR_ACCESS_DENIED;
3824                 goto done;
3825         }
3826
3827         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3828                 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3829                         lp_servicename(snum) ));
3830                 result = WERR_ACCESS_DENIED;
3831                 /*result = NT_STATUS_NO_PROBLEMO;*/
3832                 goto done;
3833         }
3834
3835         DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3836
3837         /*
3838          * Convert the on the wire devicemode format to the internal one.
3839          */
3840
3841         if (!convert_devicemode(printer->info_2->printername,
3842                                 printer_default->devmode_cont.devmode,
3843                                 &printer->info_2->devmode)) {
3844                 result = WERR_NOMEM;
3845                 goto done;
3846         }
3847
3848         /*
3849          * Finally write back to the tdb.
3850          */
3851
3852         result = add_a_printer(*printer, 2);
3853
3854   done:
3855
3856         free_a_printer(&printer, 2);
3857         return result;
3858 }