merge oops fix from 2.2
[Samba/gbeck.git] / source / printing / nt_printing.c
blob8e022ac1f6c118038cb9eb561157fda7ccb897ed
1 /*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 extern pstring global_myname;
26 extern DOM_SID global_sid_World;
28 static TDB_CONTEXT *tdb_forms; /* used for forms files */
29 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
30 static TDB_CONTEXT *tdb_printers; /* used for printers files */
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
35 #define PRINTERS_PREFIX "PRINTERS/"
36 #define SECDESC_PREFIX "SECDESC/"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
41 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_2
43 /* Map generic permissions to printer object specific permissions */
45 struct generic_mapping printer_generic_mapping = {
46 PRINTER_READ,
47 PRINTER_WRITE,
48 PRINTER_EXECUTE,
49 PRINTER_ALL_ACCESS
52 /* We need one default form to support our default printer. Msoft adds the
53 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
54 array index). Letter is always first, so (for the current code) additions
55 always put things in the correct order. */
56 static nt_forms_struct default_forms[] = {
57 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
58 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
59 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
60 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
61 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
62 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
63 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
64 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
65 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
66 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
67 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
68 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
69 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
70 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
71 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
72 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
73 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
74 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
75 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
76 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
77 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
78 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
79 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
80 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
81 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
82 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
83 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
84 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
85 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
86 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
87 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
88 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
89 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
90 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
91 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
92 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
93 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
94 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
95 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
96 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
97 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
98 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
99 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
100 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
101 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
102 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
103 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
104 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
105 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
106 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
107 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
108 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
109 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
110 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
111 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
112 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
113 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
114 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
115 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
116 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
117 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
118 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
119 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
120 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
121 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
122 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
123 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
124 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
125 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
126 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
127 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
128 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
129 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
130 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
131 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
132 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
133 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
134 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
135 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
136 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
137 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
138 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
139 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
140 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
141 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
142 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
143 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
144 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
145 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
146 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
147 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
148 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
149 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
150 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
151 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
152 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
153 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
154 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
155 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
156 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
157 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
158 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
159 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
160 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
161 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
162 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
163 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
164 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
165 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
166 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
167 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
168 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
169 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
170 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
171 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
172 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
173 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
174 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
177 static BOOL upgrade_to_version_2(void)
179 TDB_DATA kbuf, newkey, dbuf;
181 DEBUG(0,("upgrade_to_version_2: upgrading print tdb's to version 2\n"));
183 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
184 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
186 dbuf = tdb_fetch(tdb_drivers, kbuf);
188 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
189 DEBUG(0,("upgrade_to_version_2:moving form\n"));
190 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
191 DEBUG(0,("upgrade_to_version_2: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
192 return False;
194 if (tdb_delete(tdb_drivers, kbuf) != 0) {
195 DEBUG(0,("upgrade_to_version_2: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
196 return False;
200 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
201 DEBUG(0,("upgrade_to_version_2:moving printer\n"));
202 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
203 DEBUG(0,("upgrade_to_version_2: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
204 return False;
206 if (tdb_delete(tdb_drivers, kbuf) != 0) {
207 DEBUG(0,("upgrade_to_version_2: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
208 return False;
212 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
213 DEBUG(0,("upgrade_to_version_2:moving secdesc\n"));
214 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
215 DEBUG(0,("upgrade_to_version_2: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
216 return False;
218 if (tdb_delete(tdb_drivers, kbuf) != 0) {
219 DEBUG(0,("upgrade_to_version_2: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
220 return False;
224 SAFE_FREE(dbuf.dptr);
227 return True;
230 /****************************************************************************
231 open the NT printing tdb
232 ****************************************************************************/
233 BOOL nt_printing_init(void)
235 static pid_t local_pid;
236 char *vstring = "INFO/version";
238 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
239 return True;
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;
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;
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;
262 local_pid = sys_getpid();
264 /* handle a Samba upgrade */
265 tdb_lock_bystring(tdb_drivers, vstring);
266 if (tdb_fetch_int(tdb_drivers, vstring) != NTDRIVERS_DATABASE_VERSION) {
268 if (tdb_fetch_int(tdb_drivers, vstring) == NTDRIVERS_DATABASE_VERSION_1) {
269 if (!upgrade_to_version_2())
270 return False;
271 } else
272 tdb_traverse(tdb_drivers, (tdb_traverse_func)tdb_delete, NULL);
274 tdb_store_int(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
276 tdb_unlock_bystring(tdb_drivers, vstring);
278 return True;
281 /****************************************************************************
282 get builtin form struct list
283 ****************************************************************************/
284 int get_builtin_ntforms(nt_forms_struct **list)
286 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
287 return sizeof(default_forms) / sizeof(default_forms[0]);
290 /****************************************************************************
291 get a builtin form struct
292 ****************************************************************************/
294 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
296 int i,count;
297 fstring form_name;
298 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
299 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
300 count = sizeof(default_forms) / sizeof(default_forms[0]);
301 for (i=0;i<count;i++) {
302 if (strequal(form_name,default_forms[i].name)) {
303 DEBUGADD(6,("Found builtin form %s \n", form_name));
304 memcpy(form,&default_forms[i],sizeof(*form));
305 break;
309 return (i !=count);
312 /****************************************************************************
313 get a form struct list
314 ****************************************************************************/
315 int get_ntforms(nt_forms_struct **list)
317 TDB_DATA kbuf, newkey, dbuf;
318 nt_forms_struct *tl;
319 nt_forms_struct form;
320 int ret;
321 int i;
322 int n = 0;
324 for (kbuf = tdb_firstkey(tdb_forms);
325 kbuf.dptr;
326 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
327 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
329 dbuf = tdb_fetch(tdb_forms, kbuf);
330 if (!dbuf.dptr) continue;
332 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
333 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
334 &i, &form.flag, &form.width, &form.length, &form.left,
335 &form.top, &form.right, &form.bottom);
336 SAFE_FREE(dbuf.dptr);
337 if (ret != dbuf.dsize) continue;
339 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
340 if (!tl) {
341 DEBUG(0,("get_ntforms: Realloc fail.\n"));
342 return 0;
344 *list = tl;
345 (*list)[n] = form;
346 n++;
350 return n;
353 /****************************************************************************
354 write a form struct list
355 ****************************************************************************/
356 int write_ntforms(nt_forms_struct **list, int number)
358 pstring buf, key;
359 int len;
360 TDB_DATA kbuf,dbuf;
361 int i;
363 for (i=0;i<number;i++) {
364 /* save index, so list is rebuilt in correct order */
365 len = tdb_pack(buf, sizeof(buf), "dddddddd",
366 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
367 (*list)[i].left, (*list)[i].top, (*list)[i].right,
368 (*list)[i].bottom);
369 if (len > sizeof(buf)) break;
370 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
371 kbuf.dsize = strlen(key)+1;
372 kbuf.dptr = key;
373 dbuf.dsize = len;
374 dbuf.dptr = buf;
375 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
378 return i;
381 /****************************************************************************
382 add a form struct at the end of the list
383 ****************************************************************************/
384 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
386 int n=0;
387 BOOL update;
388 fstring form_name;
389 nt_forms_struct *tl;
392 * NT tries to add forms even when
393 * they are already in the base
394 * only update the values if already present
397 update=False;
399 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
400 for (n=0; n<*count; n++) {
401 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
402 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
403 update=True;
404 break;
408 if (update==False) {
409 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
410 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
411 return False;
413 *list = tl;
414 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
415 (*count)++;
418 (*list)[n].flag=form->flags;
419 (*list)[n].width=form->size_x;
420 (*list)[n].length=form->size_y;
421 (*list)[n].left=form->left;
422 (*list)[n].top=form->top;
423 (*list)[n].right=form->right;
424 (*list)[n].bottom=form->bottom;
426 return True;
429 /****************************************************************************
430 delete a named form struct
431 ****************************************************************************/
432 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
434 pstring key;
435 TDB_DATA kbuf;
436 int n=0;
437 fstring form_name;
439 *ret = WERR_OK;
441 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
443 for (n=0; n<*count; n++) {
444 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
445 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
446 break;
450 if (n == *count) {
451 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
452 *ret = WERR_INVALID_PARAM;
453 return False;
456 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
457 kbuf.dsize = strlen(key)+1;
458 kbuf.dptr = key;
459 if (tdb_delete(tdb_forms, kbuf) != 0) {
460 *ret = WERR_NOMEM;
461 return False;
464 return True;
467 /****************************************************************************
468 update a form struct
469 ****************************************************************************/
470 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
472 int n=0;
473 fstring form_name;
474 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
476 DEBUG(106, ("[%s]\n", form_name));
477 for (n=0; n<count; n++)
479 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
480 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
481 break;
484 if (n==count) return;
486 (*list)[n].flag=form->flags;
487 (*list)[n].width=form->size_x;
488 (*list)[n].length=form->size_y;
489 (*list)[n].left=form->left;
490 (*list)[n].top=form->top;
491 (*list)[n].right=form->right;
492 (*list)[n].bottom=form->bottom;
495 /****************************************************************************
496 get the nt drivers list
498 traverse the database and look-up the matching names
499 ****************************************************************************/
500 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
502 int total=0;
503 fstring short_archi;
504 fstring *fl;
505 pstring key;
506 TDB_DATA kbuf, newkey;
508 get_short_archi(short_archi, architecture);
509 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
511 for (kbuf = tdb_firstkey(tdb_drivers);
512 kbuf.dptr;
513 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
514 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
516 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
517 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
518 return -1;
520 else *list = fl;
522 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
523 total++;
526 return(total);
529 /****************************************************************************
530 function to do the mapping between the long architecture name and
531 the short one.
532 ****************************************************************************/
533 BOOL get_short_archi(char *short_archi, char *long_archi)
535 struct table {
536 char *long_archi;
537 char *short_archi;
540 struct table archi_table[]=
542 {"Windows 4.0", "WIN40" },
543 {"Windows NT x86", "W32X86" },
544 {"Windows NT R4000", "W32MIPS" },
545 {"Windows NT Alpha_AXP", "W32ALPHA" },
546 {"Windows NT PowerPC", "W32PPC" },
547 {NULL, "" }
550 int i=-1;
552 DEBUG(107,("Getting architecture dependant directory\n"));
553 do {
554 i++;
555 } while ( (archi_table[i].long_archi!=NULL ) &&
556 StrCaseCmp(long_archi, archi_table[i].long_archi) );
558 if (archi_table[i].long_archi==NULL) {
559 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
560 return False;
563 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
565 DEBUGADD(108,("index: [%d]\n", i));
566 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
567 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
569 return True;
572 /****************************************************************************
573 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
574 There are two case to be covered here: PE (Portable Executable) and NE (New
575 Executable) files. Both files support the same INFO structure, but PE files
576 store the signature in unicode, and NE files store it as !unicode.
577 ****************************************************************************/
578 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
579 uint32 *minor)
581 int i;
582 char *buf;
583 ssize_t byte_count;
585 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
586 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
587 fname, PE_HEADER_SIZE));
588 goto error_exit;
591 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
592 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
593 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
594 fname, byte_count));
595 goto no_version_info;
598 /* Is this really a DOS header? */
599 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
600 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
601 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
602 goto no_version_info;
605 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
606 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
607 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
608 fname, errno));
609 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
610 goto no_version_info;
613 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
614 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
615 fname, byte_count));
616 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
617 goto no_version_info;
620 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
621 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
622 int num_sections;
623 int section_table_bytes;
625 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
626 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
627 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
628 /* At this point, we assume the file is in error. It still could be somthing
629 * else besides a PE file, but it unlikely at this point.
631 goto error_exit;
634 /* get the section table */
635 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
636 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
637 SAFE_FREE(buf);
638 if ((buf=malloc(section_table_bytes)) == NULL) {
639 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
640 fname, section_table_bytes));
641 goto error_exit;
644 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
645 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
646 fname, byte_count));
647 goto error_exit;
650 /* Iterate the section table looking for the resource section ".rsrc" */
651 for (i = 0; i < num_sections; i++) {
652 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
654 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
655 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
656 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
658 SAFE_FREE(buf);
659 if ((buf=malloc(section_bytes)) == NULL) {
660 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
661 fname, section_bytes));
662 goto error_exit;
665 /* Seek to the start of the .rsrc section info */
666 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
667 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
668 fname, errno));
669 goto error_exit;
672 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
673 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
674 fname, byte_count));
675 goto error_exit;
678 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
679 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
680 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
681 /* Align to next long address */
682 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
684 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
685 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
686 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
688 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
689 fname, *major, *minor,
690 (*major>>16)&0xffff, *major&0xffff,
691 (*minor>>16)&0xffff, *minor&0xffff));
692 SAFE_FREE(buf);
693 return True;
700 /* Version info not found, fall back to origin date/time */
701 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
702 SAFE_FREE(buf);
703 return False;
705 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
706 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
707 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
708 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
709 /* At this point, we assume the file is in error. It still could be somthing
710 * else besides a NE file, but it unlikely at this point. */
711 goto error_exit;
714 /* Allocate a bit more space to speed up things */
715 SAFE_FREE(buf);
716 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
717 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
718 fname, PE_HEADER_SIZE));
719 goto error_exit;
722 /* This is a HACK! I got tired of trying to sort through the messy
723 * 'NE' file format. If anyone wants to clean this up please have at
724 * it, but this works. 'NE' files will eventually fade away. JRR */
725 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
726 /* Cover case that should not occur in a well formed 'NE' .dll file */
727 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
729 for(i=0; i<byte_count; i++) {
730 /* Fast skip past data that can't possibly match */
731 if (buf[i] != 'V') continue;
733 /* Potential match data crosses buf boundry, move it to beginning
734 * of buf, and fill the buf with as much as it will hold. */
735 if (i>byte_count-VS_VERSION_INFO_SIZE) {
736 int bc;
738 memcpy(buf, &buf[i], byte_count-i);
739 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
740 (byte_count-i))) < 0) {
742 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
743 fname, errno));
744 goto error_exit;
747 byte_count = bc + (byte_count - i);
748 if (byte_count<VS_VERSION_INFO_SIZE) break;
750 i = 0;
753 /* Check that the full signature string and the magic number that
754 * follows exist (not a perfect solution, but the chances that this
755 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
756 * twice, as it is simpler to read the code. */
757 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
758 /* Compute skip alignment to next long address */
759 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
760 sizeof(VS_SIGNATURE)) & 3;
761 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
763 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
764 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
765 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
766 fname, *major, *minor,
767 (*major>>16)&0xffff, *major&0xffff,
768 (*minor>>16)&0xffff, *minor&0xffff));
769 SAFE_FREE(buf);
770 return True;
775 /* Version info not found, fall back to origin date/time */
776 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
777 SAFE_FREE(buf);
778 return False;
780 } else
781 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
782 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
783 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
785 no_version_info:
786 SAFE_FREE(buf);
787 return False;
789 error_exit:
790 SAFE_FREE(buf);
791 return -1;
794 /****************************************************************************
795 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
796 share one or more files. During the MS installation process files are checked
797 to insure that only a newer version of a shared file is installed over an
798 older version. There are several possibilities for this comparison. If there
799 is no previous version, the new one is newer (obviously). If either file is
800 missing the version info structure, compare the creation date (on Unix use
801 the modification date). Otherwise chose the numerically larger version number.
802 ****************************************************************************/
803 static int file_version_is_newer(connection_struct *conn, fstring new_file,
804 fstring old_file)
806 BOOL use_version = True;
807 pstring filepath;
809 uint32 new_major;
810 uint32 new_minor;
811 time_t new_create_time;
813 uint32 old_major;
814 uint32 old_minor;
815 time_t old_create_time;
817 int access_mode;
818 int action;
819 files_struct *fsp = NULL;
820 SMB_STRUCT_STAT st;
821 SMB_STRUCT_STAT stat_buf;
822 BOOL bad_path;
824 ZERO_STRUCT(st);
825 ZERO_STRUCT(stat_buf);
826 new_create_time = (time_t)0;
827 old_create_time = (time_t)0;
829 /* Get file version info (if available) for previous file (if it exists) */
830 pstrcpy(filepath, old_file);
832 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
834 fsp = open_file_shared(conn, filepath, &stat_buf,
835 SET_OPEN_MODE(DOS_OPEN_RDONLY),
836 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
837 0, 0, &access_mode, &action);
838 if (!fsp) {
839 /* Old file not found, so by definition new file is in fact newer */
840 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
841 filepath, errno));
842 return True;
844 } else {
845 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
846 if (ret == -1) goto error_exit;
848 if (!ret) {
849 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
850 old_file));
851 use_version = False;
852 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
853 old_create_time = st.st_mtime;
854 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
857 close_file(fsp, True);
859 /* Get file version info (if available) for new file */
860 pstrcpy(filepath, new_file);
861 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
863 fsp = open_file_shared(conn, filepath, &stat_buf,
864 SET_OPEN_MODE(DOS_OPEN_RDONLY),
865 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
866 0, 0, &access_mode, &action);
867 if (!fsp) {
868 /* New file not found, this shouldn't occur if the caller did its job */
869 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
870 filepath, errno));
871 goto error_exit;
873 } else {
874 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
875 if (ret == -1) goto error_exit;
877 if (!ret) {
878 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
879 new_file));
880 use_version = False;
881 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
882 new_create_time = st.st_mtime;
883 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
886 close_file(fsp, True);
888 if (use_version) {
889 /* Compare versions and choose the larger version number */
890 if (new_major > old_major ||
891 (new_major == old_major && new_minor > old_minor)) {
893 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
894 return True;
896 else {
897 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
898 return False;
901 } else {
902 /* Compare modification time/dates and choose the newest time/date */
903 if (new_create_time > old_create_time) {
904 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
905 return True;
907 else {
908 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
909 return False;
913 error_exit:
914 if(fsp)
915 close_file(fsp, True);
916 return -1;
919 /****************************************************************************
920 Determine the correct cVersion associated with an architecture and driver
921 ****************************************************************************/
922 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
923 struct current_user *user, WERROR *perr)
925 int cversion;
926 int access_mode;
927 int action;
928 NTSTATUS nt_status;
929 pstring driverpath;
930 DATA_BLOB null_pw;
931 files_struct *fsp = NULL;
932 BOOL bad_path;
933 SMB_STRUCT_STAT st;
934 connection_struct *conn;
936 ZERO_STRUCT(st);
938 /* If architecture is Windows 95/98/ME, the version is always 0. */
939 if (strcmp(architecture, "WIN40") == 0) {
940 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
941 return 0;
944 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
945 /* Null password is ok - we are already an authenticated user... */
946 null_pw = data_blob(NULL, 0);
948 become_root();
949 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
950 unbecome_root();
952 if (conn == NULL) {
953 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
954 *perr = ntstatus_to_werror(nt_status);
955 return -1;
958 /* We are temporarily becoming the connection user. */
959 if (!become_user(conn, conn->vuid)) {
960 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
961 *perr = WERR_ACCESS_DENIED;
962 return -1;
965 /* Open the driver file (Portable Executable format) and determine the
966 * deriver the cversion. */
967 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
969 unix_convert(driverpath,conn,NULL,&bad_path,&st);
971 fsp = open_file_shared(conn, driverpath, &st,
972 SET_OPEN_MODE(DOS_OPEN_RDONLY),
973 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
974 0, 0, &access_mode, &action);
975 if (!fsp) {
976 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
977 driverpath, errno));
978 *perr = WERR_ACCESS_DENIED;
979 goto error_exit;
981 else {
982 uint32 major;
983 uint32 minor;
984 int ret = get_file_version(fsp, driverpath, &major, &minor);
985 if (ret == -1) goto error_exit;
987 if (!ret) {
988 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
989 goto error_exit;
993 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
994 * for more details. Version in this case is not just the version of the
995 * file, but the version in the sense of kernal mode (2) vs. user mode
996 * (3) drivers. Other bits of the version fields are the version info.
997 * JRR 010716
999 cversion = major & 0x0000ffff;
1000 switch (cversion) {
1001 case 2: /* WinNT drivers */
1002 case 3: /* Win2K drivers */
1003 break;
1005 default:
1006 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1007 driverpath, cversion));
1008 goto error_exit;
1011 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1012 driverpath, major, minor));
1015 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1016 driverpath, cversion));
1018 close_file(fsp, True);
1019 close_cnum(conn, user->vuid);
1020 unbecome_user();
1021 return cversion;
1023 error_exit:
1025 if(fsp)
1026 close_file(fsp, True);
1028 close_cnum(conn, user->vuid);
1029 unbecome_user();
1030 return -1;
1033 /****************************************************************************
1034 ****************************************************************************/
1035 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1036 struct current_user *user)
1038 fstring architecture;
1039 fstring new_name;
1040 char *p;
1041 int i;
1042 WERROR err;
1044 /* clean up the driver name.
1045 * we can get .\driver.dll
1046 * or worse c:\windows\system\driver.dll !
1048 /* using an intermediate string to not have overlaping memcpy()'s */
1049 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1050 fstrcpy(new_name, p+1);
1051 fstrcpy(driver->driverpath, new_name);
1054 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1055 fstrcpy(new_name, p+1);
1056 fstrcpy(driver->datafile, new_name);
1059 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1060 fstrcpy(new_name, p+1);
1061 fstrcpy(driver->configfile, new_name);
1064 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1065 fstrcpy(new_name, p+1);
1066 fstrcpy(driver->helpfile, new_name);
1069 if (driver->dependentfiles) {
1070 for (i=0; *driver->dependentfiles[i]; i++) {
1071 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1072 fstrcpy(new_name, p+1);
1073 fstrcpy(driver->dependentfiles[i], new_name);
1078 get_short_archi(architecture, driver->environment);
1080 /* jfm:7/16/2000 the client always sends the cversion=0.
1081 * The server should check which version the driver is by reading
1082 * the PE header of driver->driverpath.
1084 * For Windows 95/98 the version is 0 (so the value sent is correct)
1085 * For Windows NT (the architecture doesn't matter)
1086 * NT 3.1: cversion=0
1087 * NT 3.5/3.51: cversion=1
1088 * NT 4: cversion=2
1089 * NT2K: cversion=3
1091 if ((driver->cversion = get_correct_cversion( architecture,
1092 driver->driverpath, user, &err)) == -1)
1093 return err;
1095 return WERR_OK;
1098 /****************************************************************************
1099 ****************************************************************************/
1100 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1101 struct current_user *user)
1103 fstring architecture;
1104 fstring new_name;
1105 char *p;
1106 int i;
1107 WERROR err;
1109 /* clean up the driver name.
1110 * we can get .\driver.dll
1111 * or worse c:\windows\system\driver.dll !
1113 /* using an intermediate string to not have overlaping memcpy()'s */
1114 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1115 fstrcpy(new_name, p+1);
1116 fstrcpy(driver->driverpath, new_name);
1119 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1120 fstrcpy(new_name, p+1);
1121 fstrcpy(driver->datafile, new_name);
1124 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1125 fstrcpy(new_name, p+1);
1126 fstrcpy(driver->configfile, new_name);
1129 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1130 fstrcpy(new_name, p+1);
1131 fstrcpy(driver->helpfile, new_name);
1134 if (driver->dependentfiles) {
1135 for (i=0; *driver->dependentfiles[i]; i++) {
1136 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1137 fstrcpy(new_name, p+1);
1138 fstrcpy(driver->dependentfiles[i], new_name);
1143 get_short_archi(architecture, driver->environment);
1145 /* jfm:7/16/2000 the client always sends the cversion=0.
1146 * The server should check which version the driver is by reading
1147 * the PE header of driver->driverpath.
1149 * For Windows 95/98 the version is 0 (so the value sent is correct)
1150 * For Windows NT (the architecture doesn't matter)
1151 * NT 3.1: cversion=0
1152 * NT 3.5/3.51: cversion=1
1153 * NT 4: cversion=2
1154 * NT2K: cversion=3
1156 if ((driver->version = get_correct_cversion(architecture,
1157 driver->driverpath, user, &err)) == -1)
1158 return err;
1160 return WERR_OK;
1163 /****************************************************************************
1164 ****************************************************************************/
1165 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1166 uint32 level, struct current_user *user)
1168 switch (level) {
1169 case 3:
1171 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1172 driver=driver_abstract.info_3;
1173 return clean_up_driver_struct_level_3(driver, user);
1175 case 6:
1177 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1178 driver=driver_abstract.info_6;
1179 return clean_up_driver_struct_level_6(driver, user);
1181 default:
1182 return WERR_INVALID_PARAM;
1186 /****************************************************************************
1187 This function sucks and should be replaced. JRA.
1188 ****************************************************************************/
1190 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1192 dst->cversion = src->version;
1194 fstrcpy( dst->name, src->name);
1195 fstrcpy( dst->environment, src->environment);
1196 fstrcpy( dst->driverpath, src->driverpath);
1197 fstrcpy( dst->datafile, src->datafile);
1198 fstrcpy( dst->configfile, src->configfile);
1199 fstrcpy( dst->helpfile, src->helpfile);
1200 fstrcpy( dst->monitorname, src->monitorname);
1201 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1202 dst->dependentfiles = src->dependentfiles;
1205 #if 0 /* Debugging function */
1207 static char* ffmt(unsigned char *c){
1208 int i;
1209 static char ffmt_str[17];
1211 for (i=0; i<16; i++) {
1212 if ((c[i] < ' ') || (c[i] > '~'))
1213 ffmt_str[i]='.';
1214 else
1215 ffmt_str[i]=c[i];
1217 ffmt_str[16]='\0';
1218 return ffmt_str;
1221 #endif
1223 /****************************************************************************
1224 ****************************************************************************/
1225 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1226 struct current_user *user, WERROR *perr)
1228 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1229 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1230 fstring architecture;
1231 pstring new_dir;
1232 pstring old_name;
1233 pstring new_name;
1234 DATA_BLOB null_pw;
1235 connection_struct *conn;
1236 NTSTATUS nt_status;
1237 int ver = 0;
1238 int i;
1240 *perr = WERR_OK;
1242 if (level==3)
1243 driver=driver_abstract.info_3;
1244 else if (level==6) {
1245 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1246 driver = &converted_driver;
1247 } else {
1248 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1249 return False;
1252 get_short_archi(architecture, driver->environment);
1254 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1255 /* Null password is ok - we are already an authenticated user... */
1256 null_pw = data_blob(NULL, 0);
1257 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
1259 if (conn == NULL) {
1260 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1261 *perr = ntstatus_to_werror(nt_status);
1262 return False;
1266 * Save who we are - we are temporarily becoming the connection user.
1269 push_sec_ctx();
1271 if (!become_user(conn, conn->vuid)) {
1272 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1273 pop_sec_ctx();
1274 return False;
1278 * make the directories version and version\driver_name
1279 * under the architecture directory.
1281 DEBUG(5,("Creating first directory\n"));
1282 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1283 mkdir_internal(conn, new_dir);
1285 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1286 * listed for this driver which has already been moved, skip it (note:
1287 * drivers may list the same file name several times. Then check if the
1288 * file already exists in archi\cversion\, if so, check that the version
1289 * info (or time stamps if version info is unavailable) is newer (or the
1290 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1291 * Otherwise, delete the file.
1293 * If a file is not moved to archi\cversion\ because of an error, all the
1294 * rest of the 'unmoved' driver files are removed from archi\. If one or
1295 * more of the driver's files was already moved to archi\cversion\, it
1296 * potentially leaves the driver in a partially updated state. Version
1297 * trauma will most likely occur if an client attempts to use any printer
1298 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1299 * done is appropriate... later JRR
1302 DEBUG(5,("Moving files now !\n"));
1304 if (driver->driverpath && strlen(driver->driverpath)) {
1305 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1306 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1307 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1308 NTSTATUS status;
1309 status = rename_internals(conn, new_name, old_name, True);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1312 new_name, old_name));
1313 *perr = ntstatus_to_werror(status);
1314 unlink_internals(conn, 0, new_name);
1315 ver = -1;
1318 else
1319 unlink_internals(conn, 0, new_name);
1322 if (driver->datafile && strlen(driver->datafile)) {
1323 if (!strequal(driver->datafile, driver->driverpath)) {
1324 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1325 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1326 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1327 NTSTATUS status;
1328 status = rename_internals(conn, new_name, old_name, True);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1331 new_name, old_name));
1332 *perr = ntstatus_to_werror(status);
1333 unlink_internals(conn, 0, new_name);
1334 ver = -1;
1337 else
1338 unlink_internals(conn, 0, new_name);
1342 if (driver->configfile && strlen(driver->configfile)) {
1343 if (!strequal(driver->configfile, driver->driverpath) &&
1344 !strequal(driver->configfile, driver->datafile)) {
1345 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1346 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1347 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1348 NTSTATUS status;
1349 status = rename_internals(conn, new_name, old_name, True);
1350 if (!NT_STATUS_IS_OK(status)) {
1351 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1352 new_name, old_name));
1353 *perr = ntstatus_to_werror(status);
1354 unlink_internals(conn, 0, new_name);
1355 ver = -1;
1358 else
1359 unlink_internals(conn, 0, new_name);
1363 if (driver->helpfile && strlen(driver->helpfile)) {
1364 if (!strequal(driver->helpfile, driver->driverpath) &&
1365 !strequal(driver->helpfile, driver->datafile) &&
1366 !strequal(driver->helpfile, driver->configfile)) {
1367 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1368 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1369 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1370 NTSTATUS status;
1371 status = rename_internals(conn, new_name, old_name, True);
1372 if (!NT_STATUS_IS_OK(status)) {
1373 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1374 new_name, old_name));
1375 *perr = ntstatus_to_werror(status);
1376 unlink_internals(conn, 0, new_name);
1377 ver = -1;
1380 else
1381 unlink_internals(conn, 0, new_name);
1385 if (driver->dependentfiles) {
1386 for (i=0; *driver->dependentfiles[i]; i++) {
1387 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1388 !strequal(driver->dependentfiles[i], driver->datafile) &&
1389 !strequal(driver->dependentfiles[i], driver->configfile) &&
1390 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1391 int j;
1392 for (j=0; j < i; j++) {
1393 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1394 goto NextDriver;
1398 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1399 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1400 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1401 NTSTATUS status;
1402 status = rename_internals(conn, new_name, old_name, True);
1403 if (!NT_STATUS_IS_OK(status)) {
1404 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1405 new_name, old_name));
1406 *perr = ntstatus_to_werror(status);
1407 unlink_internals(conn, 0, new_name);
1408 ver = -1;
1411 else
1412 unlink_internals(conn, 0, new_name);
1414 NextDriver: ;
1418 close_cnum(conn, user->vuid);
1419 pop_sec_ctx();
1421 return ver == -1 ? False : True;
1424 /****************************************************************************
1425 ****************************************************************************/
1426 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1428 int len, buflen;
1429 fstring architecture;
1430 pstring directory;
1431 pstring temp_name;
1432 pstring key;
1433 char *buf;
1434 int i, ret;
1435 TDB_DATA kbuf, dbuf;
1437 get_short_archi(architecture, driver->environment);
1439 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1440 * \\server is added in the rpc server layer.
1441 * It does make sense to NOT store the server's name in the printer TDB.
1444 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1446 /* .inf files do not always list a file for each of the four standard files.
1447 * Don't prepend a path to a null filename, or client claims:
1448 * "The server on which the printer resides does not have a suitable
1449 * <printer driver name> printer driver installed. Click OK if you
1450 * wish to install the driver on your local machine."
1452 if (strlen(driver->driverpath)) {
1453 fstrcpy(temp_name, driver->driverpath);
1454 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1457 if (strlen(driver->datafile)) {
1458 fstrcpy(temp_name, driver->datafile);
1459 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1462 if (strlen(driver->configfile)) {
1463 fstrcpy(temp_name, driver->configfile);
1464 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1467 if (strlen(driver->helpfile)) {
1468 fstrcpy(temp_name, driver->helpfile);
1469 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1472 if (driver->dependentfiles) {
1473 for (i=0; *driver->dependentfiles[i]; i++) {
1474 fstrcpy(temp_name, driver->dependentfiles[i]);
1475 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1479 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1481 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1483 buf = NULL;
1484 len = buflen = 0;
1486 again:
1487 len = 0;
1488 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1489 driver->cversion,
1490 driver->name,
1491 driver->environment,
1492 driver->driverpath,
1493 driver->datafile,
1494 driver->configfile,
1495 driver->helpfile,
1496 driver->monitorname,
1497 driver->defaultdatatype);
1499 if (driver->dependentfiles) {
1500 for (i=0; *driver->dependentfiles[i]; i++) {
1501 len += tdb_pack(buf+len, buflen-len, "f",
1502 driver->dependentfiles[i]);
1506 if (len != buflen) {
1507 char *tb;
1509 tb = (char *)Realloc(buf, len);
1510 if (!tb) {
1511 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1512 ret = -1;
1513 goto done;
1515 else buf = tb;
1516 buflen = len;
1517 goto again;
1521 kbuf.dptr = key;
1522 kbuf.dsize = strlen(key)+1;
1523 dbuf.dptr = buf;
1524 dbuf.dsize = len;
1526 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1528 done:
1529 if (ret)
1530 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1532 SAFE_FREE(buf);
1533 return ret;
1536 /****************************************************************************
1537 ****************************************************************************/
1538 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1540 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1542 ZERO_STRUCT(info3);
1543 info3.cversion = driver->version;
1544 fstrcpy(info3.name,driver->name);
1545 fstrcpy(info3.environment,driver->environment);
1546 fstrcpy(info3.driverpath,driver->driverpath);
1547 fstrcpy(info3.datafile,driver->datafile);
1548 fstrcpy(info3.configfile,driver->configfile);
1549 fstrcpy(info3.helpfile,driver->helpfile);
1550 fstrcpy(info3.monitorname,driver->monitorname);
1551 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1552 info3.dependentfiles = driver->dependentfiles;
1554 return add_a_printer_driver_3(&info3);
1558 /****************************************************************************
1559 ****************************************************************************/
1560 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1562 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1564 ZERO_STRUCT(info);
1566 fstrcpy(info.name, in_prt);
1567 fstrcpy(info.defaultdatatype, "RAW");
1569 fstrcpy(info.driverpath, "");
1570 fstrcpy(info.datafile, "");
1571 fstrcpy(info.configfile, "");
1572 fstrcpy(info.helpfile, "");
1574 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1575 return WERR_NOMEM;
1577 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1578 fstrcpy(info.dependentfiles[0], "");
1580 *info_ptr = memdup(&info, sizeof(info));
1582 return WERR_OK;
1585 /****************************************************************************
1586 ****************************************************************************/
1587 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1589 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1590 TDB_DATA kbuf, dbuf;
1591 fstring architecture;
1592 int len = 0;
1593 int i;
1594 pstring key;
1596 ZERO_STRUCT(driver);
1598 get_short_archi(architecture, in_arch);
1600 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1602 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1604 kbuf.dptr = key;
1605 kbuf.dsize = strlen(key)+1;
1607 dbuf = tdb_fetch(tdb_drivers, kbuf);
1608 #if 0
1609 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1610 #else
1611 if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1612 #endif
1613 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1614 &driver.cversion,
1615 driver.name,
1616 driver.environment,
1617 driver.driverpath,
1618 driver.datafile,
1619 driver.configfile,
1620 driver.helpfile,
1621 driver.monitorname,
1622 driver.defaultdatatype);
1624 i=0;
1625 while (len < dbuf.dsize) {
1626 fstring *tddfs;
1628 tddfs = (fstring *)Realloc(driver.dependentfiles,
1629 sizeof(fstring)*(i+2));
1630 if (tddfs == NULL) {
1631 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1632 break;
1634 else driver.dependentfiles = tddfs;
1636 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1637 &driver.dependentfiles[i]);
1638 i++;
1640 if (driver.dependentfiles != NULL)
1641 fstrcpy(driver.dependentfiles[i], "");
1643 SAFE_FREE(dbuf.dptr);
1645 if (len != dbuf.dsize) {
1646 SAFE_FREE(driver.dependentfiles);
1648 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1651 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1653 return WERR_OK;
1656 /****************************************************************************
1657 ****************************************************************************/
1658 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1660 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1661 TDB_DATA kbuf;
1662 pstring key;
1663 int i;
1664 line[0] = '\0';
1666 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1667 DEBUG(10,("driver key: [%s]\n", key));
1669 kbuf.dptr = key;
1670 kbuf.dsize = strlen(key)+1;
1671 if (!tdb_exists(tdb_drivers, kbuf)) return False;
1673 ZERO_STRUCT(info3);
1674 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1676 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1677 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1678 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1679 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1680 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1681 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1682 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1684 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1685 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1686 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1688 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1689 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1690 pstrcat(line, info3->configfile);
1691 pstrcat(line, ":");
1692 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1693 pstrcat(line, info3->datafile);
1694 pstrcat(line, ":");
1695 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1696 pstrcat(line, info3->helpfile);
1697 pstrcat(line, ":");
1698 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1699 pstrcat(line, info3->monitorname);
1700 pstrcat(line, ":");
1701 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1702 pstrcat(line, ":");
1704 for (i=0; info3->dependentfiles &&
1705 *info3->dependentfiles[i]; i++) {
1706 if (i) pstrcat(line, ","); /* don't end in a "," */
1707 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1708 pstrcat(line, info3->dependentfiles[i]);
1711 SAFE_FREE(info3);
1713 return True;
1716 /****************************************************************************
1717 debugging function, dump at level 6 the struct in the logs
1718 ****************************************************************************/
1719 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1721 uint32 result;
1722 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1723 int i;
1725 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1727 switch (level)
1729 case 3:
1731 if (driver.info_3 == NULL)
1732 result=5;
1733 else {
1734 info3=driver.info_3;
1736 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1737 DEBUGADD(106,("name:[%s]\n", info3->name));
1738 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1739 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1740 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1741 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1742 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1743 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1744 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1746 for (i=0; info3->dependentfiles &&
1747 *info3->dependentfiles[i]; i++) {
1748 DEBUGADD(106,("dependentfile:[%s]\n",
1749 info3->dependentfiles[i]));
1751 result=0;
1753 break;
1755 default:
1756 DEBUGADD(1,("Level not implemented\n"));
1757 result=1;
1758 break;
1761 return result;
1764 /****************************************************************************
1765 ****************************************************************************/
1766 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1768 int len = 0;
1770 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1772 if (!nt_devmode) return len;
1774 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1775 nt_devmode->devicename,
1776 nt_devmode->formname,
1778 nt_devmode->specversion,
1779 nt_devmode->driverversion,
1780 nt_devmode->size,
1781 nt_devmode->driverextra,
1782 nt_devmode->orientation,
1783 nt_devmode->papersize,
1784 nt_devmode->paperlength,
1785 nt_devmode->paperwidth,
1786 nt_devmode->scale,
1787 nt_devmode->copies,
1788 nt_devmode->defaultsource,
1789 nt_devmode->printquality,
1790 nt_devmode->color,
1791 nt_devmode->duplex,
1792 nt_devmode->yresolution,
1793 nt_devmode->ttoption,
1794 nt_devmode->collate,
1795 nt_devmode->logpixels,
1797 nt_devmode->fields,
1798 nt_devmode->bitsperpel,
1799 nt_devmode->pelswidth,
1800 nt_devmode->pelsheight,
1801 nt_devmode->displayflags,
1802 nt_devmode->displayfrequency,
1803 nt_devmode->icmmethod,
1804 nt_devmode->icmintent,
1805 nt_devmode->mediatype,
1806 nt_devmode->dithertype,
1807 nt_devmode->reserved1,
1808 nt_devmode->reserved2,
1809 nt_devmode->panningwidth,
1810 nt_devmode->panningheight,
1811 nt_devmode->private);
1814 if (nt_devmode->private) {
1815 len += tdb_pack(buf+len, buflen-len, "B",
1816 nt_devmode->driverextra,
1817 nt_devmode->private);
1820 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1822 return len;
1825 /****************************************************************************
1826 ****************************************************************************/
1827 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1829 int len = 0;
1831 while (param != NULL) {
1832 len += tdb_pack(buf+len, buflen-len, "pfdB",
1833 param,
1834 param->value,
1835 param->type,
1836 param->data_len,
1837 param->data);
1838 param=param->next;
1841 len += tdb_pack(buf+len, buflen-len, "p", param);
1843 return len;
1847 /****************************************************************************
1848 delete a printer - this just deletes the printer info file, any open
1849 handles are not affected
1850 ****************************************************************************/
1851 uint32 del_a_printer(char *sharename)
1853 pstring key;
1854 TDB_DATA kbuf;
1856 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1858 kbuf.dptr=key;
1859 kbuf.dsize=strlen(key)+1;
1861 tdb_delete(tdb_printers, kbuf);
1862 return 0;
1865 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1866 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1867 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1868 /****************************************************************************
1869 ****************************************************************************/
1870 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1872 pstring key;
1873 char *buf;
1874 int buflen, len;
1875 WERROR ret;
1876 TDB_DATA kbuf, dbuf;
1879 * in addprinter: no servername and the printer is the name
1880 * in setprinter: servername is \\server
1881 * and printer is \\server\\printer
1883 * Samba manages only local printers.
1884 * we currently don't support things like path=\\other_server\printer
1887 if (info->servername[0]!='\0') {
1888 trim_string(info->printername, info->servername, NULL);
1889 trim_string(info->printername, "\\", NULL);
1890 info->servername[0]='\0';
1894 * JFM: one day I'll forget.
1895 * below that's info->portname because that's the SAMBA sharename
1896 * and I made NT 'thinks' it's the portname
1897 * the info->sharename is the thing you can name when you add a printer
1898 * that's the short-name when you create shared printer for 95/98
1899 * So I've made a limitation in SAMBA: you can only have 1 printer model
1900 * behind a SAMBA share.
1903 buf = NULL;
1904 buflen = 0;
1906 again:
1907 len = 0;
1908 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1909 info->attributes,
1910 info->priority,
1911 info->default_priority,
1912 info->starttime,
1913 info->untiltime,
1914 info->status,
1915 info->cjobs,
1916 info->averageppm,
1917 info->changeid,
1918 info->c_setprinter,
1919 info->setuptime,
1920 info->servername,
1921 info->printername,
1922 info->sharename,
1923 info->portname,
1924 info->drivername,
1925 info->comment,
1926 info->location,
1927 info->sepfile,
1928 info->printprocessor,
1929 info->datatype,
1930 info->parameters);
1932 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1934 len += pack_specifics(info->specific, buf+len, buflen-len);
1936 if (buflen != len) {
1937 char *tb;
1939 tb = (char *)Realloc(buf, len);
1940 if (!tb) {
1941 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1942 ret = WERR_NOMEM;
1943 goto done;
1945 else buf = tb;
1946 buflen = len;
1947 goto again;
1951 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1953 kbuf.dptr = key;
1954 kbuf.dsize = strlen(key)+1;
1955 dbuf.dptr = buf;
1956 dbuf.dsize = len;
1958 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
1960 done:
1961 if (!W_ERROR_IS_OK(ret))
1962 DEBUG(8, ("error updating printer to tdb on disk\n"));
1964 SAFE_FREE(buf);
1966 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1967 info->sharename, info->drivername, info->portname, len));
1969 return ret;
1973 /****************************************************************************
1974 ****************************************************************************/
1975 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1977 NT_PRINTER_PARAM *current;
1979 DEBUG(108,("add_a_specific_param\n"));
1981 (*param)->next=NULL;
1983 if (info_2->specific == NULL)
1985 info_2->specific=*param;
1987 else
1989 current=info_2->specific;
1990 while (current->next != NULL) {
1991 current=current->next;
1993 current->next=*param;
1996 *param = NULL;
1999 /****************************************************************************
2000 ****************************************************************************/
2001 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2003 NT_PRINTER_PARAM *current;
2004 NT_PRINTER_PARAM *previous;
2006 current=info_2->specific;
2007 previous=current;
2009 if (current==NULL) return (False);
2011 if ( !strcmp(current->value, param->value) &&
2012 (strlen(current->value)==strlen(param->value)) ) {
2013 DEBUG(109,("deleting first value\n"));
2014 info_2->specific=current->next;
2015 SAFE_FREE(current->data);
2016 SAFE_FREE(current);
2017 DEBUG(109,("deleted first value\n"));
2018 return (True);
2021 current=previous->next;
2023 while ( current!=NULL ) {
2024 if (!strcmp(current->value, param->value) &&
2025 strlen(current->value)==strlen(param->value) ) {
2026 DEBUG(109,("deleting current value\n"));
2027 previous->next=current->next;
2028 SAFE_FREE(current->data);
2029 SAFE_FREE(current);
2030 DEBUG(109,("deleted current value\n"));
2031 return(True);
2034 previous=previous->next;
2035 current=current->next;
2037 return (False);
2040 /****************************************************************************
2041 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2042 ****************************************************************************/
2043 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2045 NT_PRINTER_PARAM *param = *param_ptr;
2047 if(param == NULL)
2048 return;
2050 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2052 SAFE_FREE(param->data);
2053 SAFE_FREE(*param_ptr);
2056 /****************************************************************************
2057 Malloc and return an NT devicemode.
2058 ****************************************************************************/
2060 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2063 * should I init this ones ???
2064 nt_devmode->devicename
2067 char adevice[32];
2068 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2070 if (nt_devmode == NULL) {
2071 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2072 return NULL;
2075 ZERO_STRUCTP(nt_devmode);
2077 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2078 fstrcpy(nt_devmode->devicename, adevice);
2080 fstrcpy(nt_devmode->formname, "Letter");
2082 nt_devmode->specversion = 0x0401;
2083 nt_devmode->driverversion = 0x0400;
2084 nt_devmode->size = 0x00DC;
2085 nt_devmode->driverextra = 0x0000;
2086 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2087 DEFAULTSOURCE | COPIES | SCALE |
2088 PAPERSIZE | ORIENTATION;
2089 nt_devmode->orientation = 1;
2090 nt_devmode->papersize = PAPER_LETTER;
2091 nt_devmode->paperlength = 0;
2092 nt_devmode->paperwidth = 0;
2093 nt_devmode->scale = 0x64;
2094 nt_devmode->copies = 01;
2095 nt_devmode->defaultsource = BIN_FORMSOURCE;
2096 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2097 nt_devmode->color = COLOR_MONOCHROME;
2098 nt_devmode->duplex = DUP_SIMPLEX;
2099 nt_devmode->yresolution = 0;
2100 nt_devmode->ttoption = TT_SUBDEV;
2101 nt_devmode->collate = COLLATE_FALSE;
2102 nt_devmode->icmmethod = 0;
2103 nt_devmode->icmintent = 0;
2104 nt_devmode->mediatype = 0;
2105 nt_devmode->dithertype = 0;
2107 /* non utilisés par un driver d'imprimante */
2108 nt_devmode->logpixels = 0;
2109 nt_devmode->bitsperpel = 0;
2110 nt_devmode->pelswidth = 0;
2111 nt_devmode->pelsheight = 0;
2112 nt_devmode->displayflags = 0;
2113 nt_devmode->displayfrequency = 0;
2114 nt_devmode->reserved1 = 0;
2115 nt_devmode->reserved2 = 0;
2116 nt_devmode->panningwidth = 0;
2117 nt_devmode->panningheight = 0;
2119 nt_devmode->private = NULL;
2120 return nt_devmode;
2123 /****************************************************************************
2124 Deepcopy an NT devicemode.
2125 ****************************************************************************/
2127 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2129 NT_DEVICEMODE *new_nt_devicemode = NULL;
2131 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2132 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2133 return NULL;
2136 new_nt_devicemode->private = NULL;
2137 if (nt_devicemode->private != NULL) {
2138 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2139 SAFE_FREE(new_nt_devicemode);
2140 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2141 return NULL;
2145 return new_nt_devicemode;
2148 /****************************************************************************
2149 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2150 ****************************************************************************/
2152 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2154 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2156 if(nt_devmode == NULL)
2157 return;
2159 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2161 SAFE_FREE(nt_devmode->private);
2162 SAFE_FREE(*devmode_ptr);
2165 /****************************************************************************
2166 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2167 ****************************************************************************/
2168 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2170 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2171 NT_PRINTER_PARAM *param_ptr;
2173 if(info == NULL)
2174 return;
2176 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2178 free_nt_devicemode(&info->devmode);
2180 for(param_ptr = info->specific; param_ptr; ) {
2181 NT_PRINTER_PARAM *tofree = param_ptr;
2183 param_ptr = param_ptr->next;
2184 free_nt_printer_param(&tofree);
2187 SAFE_FREE(*info_ptr);
2191 /****************************************************************************
2192 ****************************************************************************/
2193 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2195 int len = 0;
2196 int extra_len = 0;
2197 NT_DEVICEMODE devmode;
2199 ZERO_STRUCT(devmode);
2201 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2203 if (!*nt_devmode) return len;
2205 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2206 devmode.devicename,
2207 devmode.formname,
2209 &devmode.specversion,
2210 &devmode.driverversion,
2211 &devmode.size,
2212 &devmode.driverextra,
2213 &devmode.orientation,
2214 &devmode.papersize,
2215 &devmode.paperlength,
2216 &devmode.paperwidth,
2217 &devmode.scale,
2218 &devmode.copies,
2219 &devmode.defaultsource,
2220 &devmode.printquality,
2221 &devmode.color,
2222 &devmode.duplex,
2223 &devmode.yresolution,
2224 &devmode.ttoption,
2225 &devmode.collate,
2226 &devmode.logpixels,
2228 &devmode.fields,
2229 &devmode.bitsperpel,
2230 &devmode.pelswidth,
2231 &devmode.pelsheight,
2232 &devmode.displayflags,
2233 &devmode.displayfrequency,
2234 &devmode.icmmethod,
2235 &devmode.icmintent,
2236 &devmode.mediatype,
2237 &devmode.dithertype,
2238 &devmode.reserved1,
2239 &devmode.reserved2,
2240 &devmode.panningwidth,
2241 &devmode.panningheight,
2242 &devmode.private);
2244 if (devmode.private) {
2245 /* the len in tdb_unpack is an int value and
2246 * devmode.driverextra is only a short
2248 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2249 devmode.driverextra=(uint16)extra_len;
2251 /* check to catch an invalid TDB entry so we don't segfault */
2252 if (devmode.driverextra == 0) {
2253 devmode.private = NULL;
2257 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2259 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2260 if (devmode.private)
2261 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2263 return len;
2266 /****************************************************************************
2267 ****************************************************************************/
2268 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2270 int len = 0;
2271 NT_PRINTER_PARAM param, *p;
2273 *list = NULL;
2275 while (1) {
2276 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2277 if (!p) break;
2279 len += tdb_unpack(buf+len, buflen-len, "fdB",
2280 param.value,
2281 &param.type,
2282 &param.data_len,
2283 &param.data);
2284 param.next = *list;
2285 *list = memdup(&param, sizeof(param));
2287 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2290 return len;
2293 static void map_to_os2_driver(fstring drivername)
2295 static BOOL initialised=False;
2296 static fstring last_from,last_to;
2297 char *mapfile = lp_os2_driver_map();
2298 char **lines = NULL;
2299 int numlines = 0;
2300 int i;
2302 if (!strlen(drivername))
2303 return;
2305 if (!*mapfile)
2306 return;
2308 if (!initialised) {
2309 *last_from = *last_to = 0;
2310 initialised = True;
2313 if (strequal(drivername,last_from)) {
2314 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2315 fstrcpy(drivername,last_to);
2316 return;
2319 lines = file_lines_load(mapfile, &numlines);
2320 if (numlines == 0) {
2321 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2322 return;
2325 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2327 for( i = 0; i < numlines; i++) {
2328 char *nt_name = lines[i];
2329 char *os2_name = strchr(nt_name,'=');
2331 if (!os2_name)
2332 continue;
2334 *os2_name++ = 0;
2336 while (isspace(*nt_name))
2337 nt_name++;
2339 if (!*nt_name || strchr("#;",*nt_name))
2340 continue;
2343 int l = strlen(nt_name);
2344 while (l && isspace(nt_name[l-1])) {
2345 nt_name[l-1] = 0;
2346 l--;
2350 while (isspace(*os2_name))
2351 os2_name++;
2354 int l = strlen(os2_name);
2355 while (l && isspace(os2_name[l-1])) {
2356 os2_name[l-1] = 0;
2357 l--;
2361 if (strequal(nt_name,drivername)) {
2362 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2363 fstrcpy(last_from,drivername);
2364 fstrcpy(last_to,os2_name);
2365 fstrcpy(drivername,os2_name);
2366 file_lines_free(lines);
2367 return;
2371 file_lines_free(lines);
2374 /****************************************************************************
2375 get a default printer info 2 struct
2376 ****************************************************************************/
2377 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2379 extern pstring global_myname;
2380 int snum;
2381 NT_PRINTER_INFO_LEVEL_2 info;
2383 ZERO_STRUCT(info);
2385 snum = lp_servicenumber(sharename);
2387 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2388 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2389 global_myname, sharename);
2390 fstrcpy(info.sharename, sharename);
2391 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2392 fstrcpy(info.drivername, lp_printerdriver(snum));
2394 /* by setting the driver name to an empty string, a local NT admin
2395 can now run the **local** APW to install a local printer driver
2396 for a Samba shared printer in 2.2. Without this, drivers **must** be
2397 installed on the Samba server for NT clients --jerry */
2398 #if 0 /* JERRY --do not uncomment-- */
2399 if (!*info.drivername)
2400 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2401 #endif
2404 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2406 pstrcpy(info.comment, "");
2407 fstrcpy(info.printprocessor, "winprint");
2408 fstrcpy(info.datatype, "RAW");
2410 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2411 | PRINTER_ATTRIBUTE_LOCAL \
2412 | PRINTER_ATTRIBUTE_RAW_ONLY \
2413 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2415 info.starttime = 0; /* Minutes since 12:00am GMT */
2416 info.untiltime = 0; /* Minutes since 12:00am GMT */
2417 info.priority = 1;
2418 info.default_priority = 1;
2419 info.setuptime = (uint32)time(NULL) - 86400; /* minus 1 day */
2422 * I changed this as I think it is better to have a generic
2423 * DEVMODE than to crash Win2k explorer.exe --jerry
2424 * See the HP Deskjet 990c Win2k drivers for an example.
2427 #if 0 /* JRA - NO NOT CHANGE ! */
2428 info.devmode = NULL;
2429 #else
2431 * We should not return a default devicemode, as this causes
2432 * Win2K to not send the correct one on PCL drivers. It needs to
2433 * see a null devicemode so it can then overwrite the devicemode
2434 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2436 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2437 goto fail;
2438 #endif
2440 /* This will get the current RPC talloc context, but we should be
2441 passing this as a parameter... fixme... JRA ! */
2443 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2444 goto fail;
2446 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2447 if (! *info_ptr) {
2448 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2449 goto fail;
2452 return WERR_OK;
2454 fail:
2456 if (info.devmode)
2457 free_nt_devicemode(&info.devmode);
2458 return WERR_ACCESS_DENIED;
2461 /****************************************************************************
2462 ****************************************************************************/
2463 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2465 pstring key;
2466 NT_PRINTER_INFO_LEVEL_2 info;
2467 int len = 0,
2468 devmode_length = 0;
2469 TDB_DATA kbuf, dbuf;
2470 fstring printername;
2472 ZERO_STRUCT(info);
2474 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2476 kbuf.dptr = key;
2477 kbuf.dsize = strlen(key)+1;
2479 dbuf = tdb_fetch(tdb_printers, kbuf);
2480 if (!dbuf.dptr)
2481 return get_a_printer_2_default(info_ptr, sharename);
2483 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2484 &info.attributes,
2485 &info.priority,
2486 &info.default_priority,
2487 &info.starttime,
2488 &info.untiltime,
2489 &info.status,
2490 &info.cjobs,
2491 &info.averageppm,
2492 &info.changeid,
2493 &info.c_setprinter,
2494 &info.setuptime,
2495 info.servername,
2496 info.printername,
2497 info.sharename,
2498 info.portname,
2499 info.drivername,
2500 info.comment,
2501 info.location,
2502 info.sepfile,
2503 info.printprocessor,
2504 info.datatype,
2505 info.parameters);
2507 /* Samba has to have shared raw drivers. */
2508 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2510 /* Restore the stripped strings. */
2511 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2512 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2513 info.printername);
2514 fstrcpy(info.printername, printername);
2516 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2517 #if 1
2519 * Some client drivers freak out if there is a NULL devmode
2520 * (probably the driver is not checking before accessing
2521 * the devmode pointer) --jerry
2523 if (!info.devmode)
2525 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2526 printername));
2527 info.devmode = construct_nt_devicemode(printername);
2529 #endif
2530 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2532 /* This will get the current RPC talloc context, but we should be
2533 passing this as a parameter... fixme... JRA ! */
2535 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2537 /* Fix for OS/2 drivers. */
2539 if (get_remote_arch() == RA_OS2)
2540 map_to_os2_driver(info.drivername);
2542 SAFE_FREE(dbuf.dptr);
2543 *info_ptr=memdup(&info, sizeof(info));
2545 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2546 sharename, info.printername, info.drivername));
2548 return WERR_OK;
2551 /****************************************************************************
2552 debugging function, dump at level 6 the struct in the logs
2553 ****************************************************************************/
2554 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2556 uint32 result;
2557 NT_PRINTER_INFO_LEVEL_2 *info2;
2559 DEBUG(106,("Dumping printer at level [%d]\n", level));
2561 switch (level)
2563 case 2:
2565 if (printer.info_2 == NULL)
2566 result=5;
2567 else
2569 info2=printer.info_2;
2571 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2572 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2573 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2574 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2575 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2576 DEBUGADD(106,("status:[%s]\n", werror_str(info2->status)));
2577 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2578 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2579 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2580 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2581 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2583 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2584 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2585 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2586 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2587 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2588 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2589 DEBUGADD(106,("location:[%s]\n", info2->location));
2590 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2591 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2592 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2593 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2594 result=0;
2596 break;
2598 default:
2599 DEBUGADD(1,("Level not implemented\n"));
2600 result=1;
2601 break;
2604 return result;
2607 /****************************************************************************
2608 Get the parameters we can substitute in an NT print job.
2609 ****************************************************************************/
2611 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2613 NT_PRINTER_INFO_LEVEL *printer = NULL;
2615 **printername = **sharename = **portname = '\0';
2617 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2618 return;
2620 fstrcpy(*printername, printer->info_2->printername);
2621 fstrcpy(*sharename, printer->info_2->sharename);
2622 fstrcpy(*portname, printer->info_2->portname);
2624 free_a_printer(&printer, 2);
2628 * The function below are the high level ones.
2629 * only those ones must be called from the spoolss code.
2630 * JFM.
2633 /****************************************************************************
2634 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2635 ****************************************************************************/
2637 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2639 WERROR result;
2641 dump_a_printer(printer, level);
2643 switch (level)
2645 case 2:
2647 printer.info_2->c_setprinter++;
2648 result=update_a_printer_2(printer.info_2);
2649 break;
2651 default:
2652 result=WERR_UNKNOWN_LEVEL;
2653 break;
2656 return result;
2659 /****************************************************************************
2660 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2661 We split this out from mod_a_printer as it updates the id's and timestamps.
2662 ****************************************************************************/
2664 WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2666 WERROR result;
2668 dump_a_printer(printer, level);
2670 switch (level)
2672 case 2:
2675 * Update the changestamp.
2676 * Note we must *not* do this in mod_a_printer().
2678 NTTIME time_nt;
2679 time_t time_unix = time(NULL);
2680 unix_to_nt_time(&time_nt, time_unix);
2681 if (printer.info_2->changeid==time_nt.low)
2682 printer.info_2->changeid++;
2683 else
2684 printer.info_2->changeid=time_nt.low;
2686 printer.info_2->c_setprinter++;
2688 result=update_a_printer_2(printer.info_2);
2689 break;
2691 default:
2692 result=WERR_UNKNOWN_LEVEL;
2693 break;
2696 return result;
2699 /****************************************************************************
2700 Initialize printer devmode & data with previously saved driver init values.
2701 ****************************************************************************/
2702 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2704 int len = 0;
2705 pstring key;
2706 TDB_DATA kbuf, dbuf;
2707 NT_PRINTER_PARAM *current;
2708 NT_PRINTER_INFO_LEVEL_2 info;
2710 ZERO_STRUCT(info);
2712 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2714 kbuf.dptr = key;
2715 kbuf.dsize = strlen(key)+1;
2717 dbuf = tdb_fetch(tdb_drivers, kbuf);
2718 if (!dbuf.dptr)
2719 return False;
2722 * Get the saved DEVMODE..
2724 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2727 * The saved DEVMODE contains the devicename from the printer used during
2728 * the initialization save. Change it to reflect the new printer.
2730 ZERO_STRUCT(info.devmode->devicename);
2731 fstrcpy(info.devmode->devicename, info_ptr->printername);
2734 * Bind the saved DEVMODE to the new the printer.
2736 free_nt_devicemode(&info_ptr->devmode);
2737 info_ptr->devmode = info.devmode;
2739 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2740 info_ptr->printername, info_ptr->drivername));
2743 * There should not be any printer data 'specifics' already set during the
2744 * add printer operation, if there are delete them.
2746 while ( (current=info_ptr->specific) != NULL ) {
2747 info_ptr->specific=current->next;
2748 SAFE_FREE(current->data);
2749 SAFE_FREE(current);
2753 * Add the printer data 'specifics' to the new printer
2755 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2757 SAFE_FREE(dbuf.dptr);
2759 return True;
2762 /****************************************************************************
2763 Initialize printer devmode & data with previously saved driver init values.
2764 When a printer is created using AddPrinter, the drivername bound to the
2765 printer is used to lookup previously saved driver initialization info, which
2766 is bound to the new printer.
2767 ****************************************************************************/
2769 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2771 uint32 result;
2773 switch (level)
2775 case 2:
2777 result=set_driver_init_2(printer->info_2);
2778 break;
2780 default:
2781 result=1;
2782 break;
2785 return result;
2788 /****************************************************************************
2789 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2790 in the tdb. Note: this is different from the driver entry and the printer
2791 entry. There should be a single driver init entry for each driver regardless
2792 of whether it was installed from NT or 2K. Technically, they should be
2793 different, but they work out to the same struct.
2794 ****************************************************************************/
2795 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2797 pstring key;
2798 char *buf;
2799 int buflen, len, ret;
2800 TDB_DATA kbuf, dbuf;
2802 buf = NULL;
2803 buflen = 0;
2805 again:
2806 len = 0;
2807 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2809 len += pack_specifics(info->specific, buf+len, buflen-len);
2811 if (buflen != len) {
2812 char *tb;
2814 tb = (char *)Realloc(buf, len);
2815 if (!tb) {
2816 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2817 ret = -1;
2818 goto done;
2820 else buf = tb;
2821 buflen = len;
2822 goto again;
2825 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2827 kbuf.dptr = key;
2828 kbuf.dsize = strlen(key)+1;
2829 dbuf.dptr = buf;
2830 dbuf.dsize = len;
2832 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2834 done:
2835 if (ret == -1)
2836 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2838 SAFE_FREE(buf);
2840 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2841 info->sharename, info->drivername));
2843 return ret;
2846 /****************************************************************************
2847 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2848 ****************************************************************************/
2850 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2852 uint32 result;
2854 dump_a_printer(printer, level);
2856 switch (level)
2858 case 2:
2860 result=update_driver_init_2(printer.info_2);
2861 break;
2863 default:
2864 result=1;
2865 break;
2868 return result;
2871 /****************************************************************************
2872 Convert the printer data value, a REG_BINARY array, into an initialization
2873 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2874 got to keep the endians happy :).
2875 ****************************************************************************/
2877 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2879 BOOL result = False;
2880 prs_struct ps;
2881 DEVICEMODE devmode;
2883 ZERO_STRUCT(devmode);
2885 prs_init(&ps, 0, ctx, UNMARSHALL);
2886 ps.data_p = (char *)param->data;
2887 ps.buffer_size = param->data_len;
2889 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2890 result = convert_devicemode("", &devmode, &nt_devmode);
2891 else
2892 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2894 return result;
2897 /****************************************************************************
2898 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2900 1. Use the driver's config DLL to this UNC printername and:
2901 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2902 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2903 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2905 The last step triggers saving the "driver initialization" information for
2906 this printer into the tdb. Later, new printers that use this driver will
2907 have this initialization information bound to them. This simulates the
2908 driver initialization, as if it had run on the Samba server (as it would
2909 have done on NT).
2911 The Win32 client side code requirement sucks! But until we can run arbitrary
2912 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2914 It would have been easier to use SetPrinter because all the UNMARSHALLING of
2915 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2916 about it and you will realize why. JRR 010720
2917 ****************************************************************************/
2919 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2921 WERROR status = WERR_OK;
2922 TALLOC_CTX *ctx = NULL;
2923 NT_DEVICEMODE *nt_devmode = NULL;
2924 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2927 * Set devmode on printer info, so entire printer initialization can be
2928 * saved to tdb.
2930 if ((ctx = talloc_init()) == NULL)
2931 return WERR_NOMEM;
2933 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2934 status = WERR_NOMEM;
2935 goto done;
2938 ZERO_STRUCTP(nt_devmode);
2941 * The DEVMODE is held in the 'data' component of the param in raw binary.
2942 * Convert it to to a devmode structure
2944 if (!convert_driver_init(param, ctx, nt_devmode)) {
2945 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
2946 status = WERR_INVALID_PARAM;
2947 goto done;
2951 * Pack up and add (or update) the DEVMODE and any current printer data to
2952 * a 'driver init' element in the tdb
2955 printer->info_2->devmode = nt_devmode;
2956 if (update_driver_init(*printer, 2)!=0) {
2957 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
2958 status = WERR_NOMEM;
2959 goto done;
2963 * If driver initialization info was successfully saved, set the current
2964 * printer to match it. This allows initialization of the current printer
2965 * as well as the driver.
2967 status = mod_a_printer(*printer, 2);
2968 if (!W_ERROR_IS_OK(status)) {
2969 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
2970 printer->info_2->printername));
2973 done:
2974 talloc_destroy(ctx);
2975 if (nt_devmode)
2976 SAFE_FREE(nt_devmode->private);
2977 SAFE_FREE(nt_devmode);
2978 printer->info_2->devmode = tmp_devmode;
2980 return status;
2983 /****************************************************************************
2984 Update the driver init info (DEVMODE and specifics) for a printer
2985 ****************************************************************************/
2987 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
2989 WERROR status = WERR_OK;
2991 switch (level)
2993 case 2:
2995 status=save_driver_init_2(printer, param);
2996 break;
2998 default:
2999 status=WERR_UNKNOWN_LEVEL;
3000 break;
3003 return status;
3006 /****************************************************************************
3007 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3008 ****************************************************************************/
3010 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3012 WERROR result;
3013 NT_PRINTER_INFO_LEVEL *printer = NULL;
3015 *pp_printer = NULL;
3017 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3019 switch (level)
3021 case 2:
3023 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3024 DEBUG(0,("get_a_printer: malloc fail.\n"));
3025 return WERR_NOMEM;
3027 ZERO_STRUCTP(printer);
3028 result=get_a_printer_2(&printer->info_2, sharename);
3029 if (W_ERROR_IS_OK(result)) {
3030 dump_a_printer(*printer, level);
3031 *pp_printer = printer;
3032 } else {
3033 SAFE_FREE(printer);
3035 break;
3037 default:
3038 result=WERR_UNKNOWN_LEVEL;
3039 break;
3042 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, werror_str(result)));
3044 return result;
3047 /****************************************************************************
3048 Deletes a NT_PRINTER_INFO_LEVEL struct.
3049 ****************************************************************************/
3051 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3053 uint32 result;
3054 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3056 DEBUG(104,("freeing a printer at level [%d]\n", level));
3058 if (printer == NULL)
3059 return 0;
3061 switch (level)
3063 case 2:
3065 if (printer->info_2 != NULL)
3067 free_nt_printer_info_level_2(&printer->info_2);
3068 result=0;
3070 else
3072 result=4;
3074 break;
3076 default:
3077 result=1;
3078 break;
3081 SAFE_FREE(*pp_printer);
3082 return result;
3085 /****************************************************************************
3086 ****************************************************************************/
3087 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3089 uint32 result;
3090 DEBUG(104,("adding a printer at level [%d]\n", level));
3091 dump_a_printer_driver(driver, level);
3093 switch (level)
3095 case 3:
3097 result=add_a_printer_driver_3(driver.info_3);
3098 break;
3101 case 6:
3103 result=add_a_printer_driver_6(driver.info_6);
3104 break;
3106 default:
3107 result=1;
3108 break;
3111 return result;
3113 /****************************************************************************
3114 ****************************************************************************/
3115 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3116 fstring printername, fstring architecture, uint32 version)
3118 WERROR result;
3120 switch (level)
3122 case 3:
3124 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3125 break;
3127 default:
3128 result=W_ERROR(1);
3129 break;
3132 if (W_ERROR_IS_OK(result))
3133 dump_a_printer_driver(*driver, level);
3134 return result;
3137 /****************************************************************************
3138 ****************************************************************************/
3139 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3141 uint32 result;
3143 switch (level)
3145 case 3:
3147 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3148 if (driver.info_3 != NULL)
3150 info3=driver.info_3;
3151 SAFE_FREE(info3->dependentfiles);
3152 ZERO_STRUCTP(info3);
3153 SAFE_FREE(info3);
3154 result=0;
3156 else
3158 result=4;
3160 break;
3162 case 6:
3164 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3165 if (driver.info_6 != NULL)
3167 info6=driver.info_6;
3168 SAFE_FREE(info6->dependentfiles);
3169 SAFE_FREE(info6->previousnames);
3170 ZERO_STRUCTP(info6);
3171 SAFE_FREE(info6);
3172 result=0;
3174 else
3176 result=4;
3178 break;
3180 default:
3181 result=1;
3182 break;
3184 return result;
3188 /****************************************************************************
3189 Determine whether or not a particular driver is currently assigned
3190 to a printer
3191 ****************************************************************************/
3192 BOOL printer_driver_in_use (char *arch, char *driver)
3194 TDB_DATA kbuf, newkey, dbuf;
3195 NT_PRINTER_INFO_LEVEL_2 info;
3196 int ret;
3198 if (!tdb_printers)
3199 if (!nt_printing_init())
3200 return False;
3202 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3204 /* loop through the printers.tdb and check for the drivername */
3205 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3206 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3209 dbuf = tdb_fetch(tdb_printers, kbuf);
3210 if (!dbuf.dptr)
3211 continue;
3213 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3214 continue;
3216 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3217 &info.attributes,
3218 &info.priority,
3219 &info.default_priority,
3220 &info.starttime,
3221 &info.untiltime,
3222 &info.status,
3223 &info.cjobs,
3224 &info.averageppm,
3225 &info.changeid,
3226 &info.c_setprinter,
3227 &info.setuptime,
3228 info.servername,
3229 info.printername,
3230 info.sharename,
3231 info.portname,
3232 info.drivername,
3233 info.comment,
3234 info.location,
3235 info.sepfile,
3236 info.printprocessor,
3237 info.datatype,
3238 info.parameters);
3240 SAFE_FREE(dbuf.dptr);
3242 if (ret == -1) {
3243 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3244 info.printername));
3245 continue;
3248 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3249 info.printername, info.drivername));
3251 if (strcmp(info.drivername, driver) == 0)
3253 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3254 info.printername, driver));
3255 return True;
3258 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3262 /* report that the driver is in use by default */
3263 return False;
3266 /****************************************************************************
3267 Remove a printer driver from the TDB. This assumes that the the driver was
3268 previously looked up.
3269 ***************************************************************************/
3270 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3272 pstring key;
3273 fstring arch;
3274 TDB_DATA kbuf;
3277 get_short_archi(arch, i->environment);
3278 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3279 arch, i->cversion, i->name);
3280 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3282 kbuf.dptr=key;
3283 kbuf.dsize=strlen(key)+1;
3285 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3286 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3287 return WERR_ACCESS_DENIED;
3290 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3291 i->name));
3293 return WERR_OK;
3295 /****************************************************************************
3296 ****************************************************************************/
3297 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3298 fstring value, uint8 **data, uint32 *type, uint32 *len)
3300 /* right now that's enough ! */
3301 NT_PRINTER_PARAM *param;
3302 int i=0;
3304 param=printer.info_2->specific;
3306 while (param != NULL && i < param_index) {
3307 param=param->next;
3308 i++;
3311 if (param == NULL)
3312 return False;
3314 /* exited because it exist */
3315 *type=param->type;
3316 StrnCpy(value, param->value, sizeof(fstring)-1);
3317 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3318 if(*data == NULL)
3319 return False;
3320 ZERO_STRUCTP(*data);
3321 memcpy(*data, param->data, param->data_len);
3322 *len=param->data_len;
3323 return True;
3326 /****************************************************************************
3327 ****************************************************************************/
3328 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3329 fstring value, uint8 **data, uint32 *type, uint32 *len)
3331 /* right now that's enough ! */
3332 NT_PRINTER_PARAM *param;
3334 DEBUG(10, ("get_specific_param\n"));
3336 param=printer.info_2->specific;
3338 while (param != NULL)
3340 #if 1 /* JRA - I think this should be case insensitive.... */
3341 if ( strequal(value, param->value)
3342 #else
3343 if ( !strcmp(value, param->value)
3344 #endif
3345 && strlen(value)==strlen(param->value))
3346 break;
3348 param=param->next;
3351 if (param != NULL)
3353 DEBUGADD(10, ("get_specific_param: found one param\n"));
3354 /* exited because it exist */
3355 *type=param->type;
3357 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3358 if(*data == NULL)
3359 return False;
3360 memcpy(*data, param->data, param->data_len);
3361 *len=param->data_len;
3363 DEBUGADD(10, ("get_specific_param: exit true\n"));
3364 return (True);
3366 DEBUGADD(10, ("get_specific_param: exit false\n"));
3367 return (False);
3370 /****************************************************************************
3371 Store a security desc for a printer.
3372 ****************************************************************************/
3374 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3376 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3377 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3378 prs_struct ps;
3379 TALLOC_CTX *mem_ctx = NULL;
3380 fstring key;
3381 WERROR status;
3383 mem_ctx = talloc_init();
3384 if (mem_ctx == NULL)
3385 return WERR_NOMEM;
3387 /* The old owner and group sids of the security descriptor are not
3388 present when new ACEs are added or removed by changing printer
3389 permissions through NT. If they are NULL in the new security
3390 descriptor then copy them over from the old one. */
3392 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3393 DOM_SID *owner_sid, *group_sid;
3394 SEC_ACL *dacl, *sacl;
3395 SEC_DESC *psd = NULL;
3396 size_t size;
3398 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3400 /* Pick out correct owner and group sids */
3402 owner_sid = secdesc_ctr->sec->owner_sid ?
3403 secdesc_ctr->sec->owner_sid :
3404 old_secdesc_ctr->sec->owner_sid;
3406 group_sid = secdesc_ctr->sec->grp_sid ?
3407 secdesc_ctr->sec->grp_sid :
3408 old_secdesc_ctr->sec->grp_sid;
3410 dacl = secdesc_ctr->sec->dacl ?
3411 secdesc_ctr->sec->dacl :
3412 old_secdesc_ctr->sec->dacl;
3414 sacl = secdesc_ctr->sec->sacl ?
3415 secdesc_ctr->sec->sacl :
3416 old_secdesc_ctr->sec->sacl;
3418 /* Make a deep copy of the security descriptor */
3420 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3421 owner_sid, group_sid,
3422 sacl,
3423 dacl,
3424 &size);
3426 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3429 if (!new_secdesc_ctr) {
3430 new_secdesc_ctr = secdesc_ctr;
3433 /* Store the security descriptor in a tdb */
3435 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3436 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3438 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3439 &ps, 1)) {
3440 status = WERR_BADFUNC;
3441 goto out;
3444 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3446 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3447 status = WERR_OK;
3448 } else {
3449 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3450 status = WERR_BADFUNC;
3453 /* Free malloc'ed memory */
3455 out:
3457 prs_mem_free(&ps);
3458 if (mem_ctx)
3459 talloc_destroy(mem_ctx);
3460 return status;
3463 /****************************************************************************
3464 Construct a default security descriptor buffer for a printer.
3465 ****************************************************************************/
3467 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3469 SEC_ACE ace[3];
3470 SEC_ACCESS sa;
3471 SEC_ACL *psa = NULL;
3472 SEC_DESC_BUF *sdb = NULL;
3473 SEC_DESC *psd = NULL;
3474 DOM_SID owner_sid;
3475 size_t sd_size;
3476 enum SID_NAME_USE name_type;
3478 /* Create an ACE where Everyone is allowed to print */
3480 init_sec_access(&sa, PRINTER_ACE_PRINT);
3481 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3482 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3484 /* Make the security descriptor owned by the Administrators group
3485 on the PDC of the domain. */
3487 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3488 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3489 } else {
3490 uint32 owner_rid;
3492 /* Backup plan - make printer owned by admins or root.
3493 This should emulate a lanman printer as security
3494 settings can't be changed. */
3496 sid_peek_rid(&owner_sid, &owner_rid);
3498 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3499 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3500 owner_rid != DOMAIN_USER_RID_ADMIN &&
3501 !lookup_name("root", &owner_sid, &name_type)) {
3502 sid_copy(&owner_sid, &global_sid_World);
3506 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3507 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3508 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3509 SEC_ACE_FLAG_INHERIT_ONLY);
3511 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3512 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3513 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3515 /* The ACL revision number in rpc_secdesc.h differs from the one
3516 created by NT when setting ACE entries in printer
3517 descriptors. NT4 complains about the property being edited by a
3518 NT5 machine. */
3520 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3521 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3522 &owner_sid, NULL,
3523 NULL, psa, &sd_size);
3526 if (!psd) {
3527 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3528 return NULL;
3531 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3533 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3534 (unsigned int)sd_size));
3536 return sdb;
3539 /****************************************************************************
3540 Get a security desc for a printer.
3541 ****************************************************************************/
3543 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3545 prs_struct ps;
3546 fstring key;
3547 char *temp;
3549 if ((temp = strchr(printername + 2, '\\'))) {
3550 printername = temp + 1;
3553 /* Fetch security descriptor from tdb */
3555 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3557 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3558 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3560 DEBUG(4,("using default secdesc for %s\n", printername));
3562 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3563 return False;
3566 return True;
3569 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3570 this security descriptor has been created when winbindd was
3571 down. Take ownership of security descriptor. */
3573 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3574 DOM_SID owner_sid;
3575 enum SID_NAME_USE name_type;
3577 /* Change sd owner to workgroup administrator */
3579 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3580 &name_type)) {
3581 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3582 SEC_DESC *psd = NULL;
3583 size_t size;
3585 /* Create new sd */
3587 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3589 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3590 &owner_sid,
3591 (*secdesc_ctr)->sec->grp_sid,
3592 (*secdesc_ctr)->sec->sacl,
3593 (*secdesc_ctr)->sec->dacl,
3594 &size);
3596 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3598 /* Swap with other one */
3600 *secdesc_ctr = new_secdesc_ctr;
3602 /* Set it */
3604 nt_printing_setsec(printername, *secdesc_ctr);
3608 if (DEBUGLEVEL >= 10) {
3609 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3610 int i;
3612 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3613 printername, the_acl->num_aces));
3615 for (i = 0; i < the_acl->num_aces; i++) {
3616 fstring sid_str;
3618 sid_to_string(sid_str, &the_acl->ace[i].sid);
3620 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3621 the_acl->ace[i].type, the_acl->ace[i].flags,
3622 the_acl->ace[i].info.mask));
3626 prs_mem_free(&ps);
3627 return True;
3630 /* error code:
3631 0: everything OK
3632 1: level not implemented
3633 2: file doesn't exist
3634 3: can't allocate memory
3635 4: can't free memory
3636 5: non existant struct
3640 A printer and a printer driver are 2 different things.
3641 NT manages them separatelly, Samba does the same.
3642 Why ? Simply because it's easier and it makes sense !
3644 Now explanation: You have 3 printers behind your samba server,
3645 2 of them are the same make and model (laser A and B). But laser B
3646 has an 3000 sheet feeder and laser A doesn't such an option.
3647 Your third printer is an old dot-matrix model for the accounting :-).
3649 If the /usr/local/samba/lib directory (default dir), you will have
3650 5 files to describe all of this.
3652 3 files for the printers (1 by printer):
3653 NTprinter_laser A
3654 NTprinter_laser B
3655 NTprinter_accounting
3656 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3657 NTdriver_printer model X
3658 NTdriver_printer model Y
3660 jfm: I should use this comment for the text file to explain
3661 same thing for the forms BTW.
3662 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3666 /* Convert generic access rights to printer object specific access rights.
3667 It turns out that NT4 security descriptors use generic access rights and
3668 NT5 the object specific ones. */
3670 void map_printer_permissions(SEC_DESC *sd)
3672 int i;
3674 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3675 se_map_generic(&sd->dacl->ace[i].info.mask,
3676 &printer_generic_mapping);
3680 /****************************************************************************
3681 Check a user has permissions to perform the given operation. We use the
3682 permission constants defined in include/rpc_spoolss.h to check the various
3683 actions we perform when checking printer access.
3685 PRINTER_ACCESS_ADMINISTER:
3686 print_queue_pause, print_queue_resume, update_printer_sec,
3687 update_printer, spoolss_addprinterex_level_2,
3688 _spoolss_setprinterdata
3690 PRINTER_ACCESS_USE:
3691 print_job_start
3693 JOB_ACCESS_ADMINISTER:
3694 print_job_delete, print_job_pause, print_job_resume,
3695 print_queue_purge
3697 ****************************************************************************/
3698 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3700 SEC_DESC_BUF *secdesc = NULL;
3701 uint32 access_granted;
3702 NTSTATUS status;
3703 BOOL result;
3704 char *pname;
3705 TALLOC_CTX *mem_ctx = NULL;
3706 extern struct current_user current_user;
3708 /* If user is NULL then use the current_user structure */
3710 if (!user)
3711 user = &current_user;
3713 /* Always allow root or printer admins to do anything */
3715 if (user->uid == 0 ||
3716 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3717 return True;
3720 /* Get printer name */
3722 pname = PRINTERNAME(snum);
3724 if (!pname || !*pname) {
3725 errno = EACCES;
3726 return False;
3729 /* Get printer security descriptor */
3731 if(!(mem_ctx = talloc_init())) {
3732 errno = ENOMEM;
3733 return False;
3736 nt_printing_getsec(mem_ctx, pname, &secdesc);
3738 if (access_type == JOB_ACCESS_ADMINISTER) {
3739 SEC_DESC_BUF *parent_secdesc = secdesc;
3741 /* Create a child security descriptor to check permissions
3742 against. This is because print jobs are child objects
3743 objects of a printer. */
3745 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3747 /* Now this is the bit that really confuses me. The access
3748 type needs to be changed from JOB_ACCESS_ADMINISTER to
3749 PRINTER_ACCESS_ADMINISTER for this to work. Something
3750 to do with the child (job) object becoming like a
3751 printer?? -tpot */
3753 access_type = PRINTER_ACCESS_ADMINISTER;
3756 /* Check access */
3758 map_printer_permissions(secdesc->sec);
3760 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
3761 &access_granted, &status);
3763 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3765 talloc_destroy(mem_ctx);
3767 if (!result)
3768 errno = EACCES;
3770 return result;
3773 /****************************************************************************
3774 Check the time parameters allow a print operation.
3775 *****************************************************************************/
3777 BOOL print_time_access_check(int snum)
3779 NT_PRINTER_INFO_LEVEL *printer = NULL;
3780 BOOL ok = False;
3781 time_t now = time(NULL);
3782 struct tm *t;
3783 uint32 mins;
3785 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3786 return False;
3788 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3789 ok = True;
3791 t = gmtime(&now);
3792 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3794 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3795 ok = True;
3797 free_a_printer(&printer, 2);
3799 if (!ok)
3800 errno = EACCES;
3802 return ok;
3805 /****************************************************************************
3806 Attempt to write a default device.
3807 *****************************************************************************/
3809 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3811 NT_PRINTER_INFO_LEVEL *printer = NULL;
3812 WERROR result;
3815 * Don't bother if no default devicemode was sent.
3818 if (printer_default->devmode_cont.devmode == NULL)
3819 return WERR_OK;
3821 result = get_a_printer(&printer, 2, lp_servicename(snum));
3822 if (!W_ERROR_IS_OK(result)) return result;
3825 * Just ignore it if we already have a devmode.
3827 #if 0
3828 if (printer->info_2->devmode != NULL)
3829 goto done;
3830 #endif
3832 * We don't have a devicemode and we're trying to write
3833 * one. Check we have the access needed.
3835 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3837 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3838 PRINTER_ACCESS_ADMINISTER) {
3839 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3840 result = WERR_ACCESS_DENIED;
3841 goto done;
3844 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3845 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3846 lp_servicename(snum) ));
3847 result = WERR_ACCESS_DENIED;
3848 /*result = NT_STATUS_NO_PROBLEMO;*/
3849 goto done;
3852 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3855 * Convert the on the wire devicemode format to the internal one.
3858 if (!convert_devicemode(printer->info_2->printername,
3859 printer_default->devmode_cont.devmode,
3860 &printer->info_2->devmode)) {
3861 result = WERR_NOMEM;
3862 goto done;
3866 * Finally write back to the tdb.
3869 result = add_a_printer(*printer, 2);
3871 done:
3873 free_a_printer(&printer, 2);
3874 return result;