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