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