2 * Unix SMB/Netbios implementation.
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.
25 extern int DEBUGLEVEL;
26 extern pstring global_myname;
27 extern DOM_SID global_sid_World;
29 static TDB_CONTEXT *tdb; /* used for driver files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define PRINTERS_PREFIX "PRINTERS/"
35 #define NTDRIVERS_DATABASE_VERSION 1
37 /* Map generic permissions to printer object specific permissions */
39 struct generic_mapping printer_generic_mapping = {
46 /* We need one default form to support our default printer. Msoft adds the
47 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
48 array index). Letter is always first, so (for the current code) additions
49 always put things in the correct order. */
50 static nt_forms_struct default_forms[] = {
51 {"Letter", 0x2, 0x34b5b, 0x44367, 0x0, 0x0, 0x34b5b, 0x44367},
53 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
54 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
55 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
56 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
57 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
58 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
59 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
60 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
61 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
62 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
63 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
64 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
65 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
66 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
67 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
68 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
69 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
70 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
71 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
72 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
73 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
74 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
75 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
76 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
77 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
78 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
79 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
80 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
81 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
82 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
83 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
84 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
85 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
86 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
87 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
88 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
89 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
90 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
91 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
92 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
93 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
94 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
95 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
96 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
97 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
98 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
99 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
100 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
101 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
102 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
103 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
104 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
105 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
106 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
107 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
108 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
109 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
110 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
111 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
112 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
113 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
114 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
115 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
116 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
117 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
118 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
119 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
120 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
121 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
122 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
123 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
124 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
125 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
126 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
127 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
128 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
129 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
130 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
131 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
132 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
133 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
134 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
135 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
136 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
137 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
138 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
139 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
140 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
141 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
142 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
143 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
144 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
145 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
146 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
147 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
148 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
149 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
150 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
151 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
152 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
153 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
154 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
155 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
156 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
157 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
158 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
159 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
160 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
161 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
162 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
163 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
164 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
165 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
166 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
167 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
168 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
169 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
170 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
174 /****************************************************************************
175 open the NT printing tdb
176 ****************************************************************************/
177 BOOL nt_printing_init(void)
179 static pid_t local_pid;
180 char *vstring = "INFO/version";
182 if (tdb && local_pid == sys_getpid()) return True;
183 tdb = tdb_open(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
185 DEBUG(0,("Failed to open nt drivers database %s (%s)\n",
186 lock_path("ntdrivers.tdb"), strerror(errno) ));
190 local_pid = sys_getpid();
192 /* handle a Samba upgrade */
193 tdb_lock_bystring(tdb, vstring);
194 if (tdb_fetch_int(tdb, vstring) != NTDRIVERS_DATABASE_VERSION) {
195 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
196 tdb_store_int(tdb, vstring, NTDRIVERS_DATABASE_VERSION);
198 tdb_unlock_bystring(tdb, vstring);
203 /****************************************************************************
204 get builtin form struct list
205 ****************************************************************************/
206 int get_builtin_ntforms(nt_forms_struct **list)
208 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
209 return sizeof(default_forms) / sizeof(default_forms[0]);
212 /****************************************************************************
213 get a builtin form struct
214 ****************************************************************************/
216 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
220 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
221 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
222 count = sizeof(default_forms) / sizeof(default_forms[0]);
223 for (i=0;i<count;i++) {
224 if (strequal(form_name,default_forms[i].name)) {
225 DEBUGADD(6,("Found builtin form %s \n", form_name));
226 memcpy(form,&default_forms[i],sizeof(*form));
234 /****************************************************************************
235 get a form struct list
236 ****************************************************************************/
237 int get_ntforms(nt_forms_struct **list)
239 TDB_DATA kbuf, newkey, dbuf;
240 nt_forms_struct form;
245 for (kbuf = tdb_firstkey(tdb);
247 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
248 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
250 dbuf = tdb_fetch(tdb, kbuf);
251 if (!dbuf.dptr) continue;
253 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
254 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
255 &i, &form.flag, &form.width, &form.length, &form.left,
256 &form.top, &form.right, &form.bottom);
257 safe_free(dbuf.dptr);
258 if (ret != dbuf.dsize) continue;
260 *list = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
262 DEBUG(0,("get_ntforms: Realloc fail.\n"));
273 /****************************************************************************
274 write a form struct list
275 ****************************************************************************/
276 int write_ntforms(nt_forms_struct **list, int number)
283 for (i=0;i<number;i++) {
284 /* save index, so list is rebuilt in correct order */
285 len = tdb_pack(buf, sizeof(buf), "dddddddd",
286 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
287 (*list)[i].left, (*list)[i].top, (*list)[i].right,
289 if (len > sizeof(buf)) break;
290 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
291 dos_to_unix(key, True); /* Convert key to unix-codepage */
292 kbuf.dsize = strlen(key)+1;
296 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
302 /****************************************************************************
303 add a form struct at the end of the list
304 ****************************************************************************/
305 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
312 * NT tries to add forms even when
313 * they are already in the base
314 * only update the values if already present
319 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
320 for (n=0; n<*count; n++) {
321 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
322 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
329 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
331 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
335 (*list)[n].flag=form->flags;
336 (*list)[n].width=form->size_x;
337 (*list)[n].length=form->size_y;
338 (*list)[n].left=form->left;
339 (*list)[n].top=form->top;
340 (*list)[n].right=form->right;
341 (*list)[n].bottom=form->bottom;
346 /****************************************************************************
347 delete a named form struct
348 ****************************************************************************/
349 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
358 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
360 for (n=0; n<*count; n++) {
361 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
362 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
368 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
369 *ret = ERROR_INVALID_PARAMETER;
373 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
374 dos_to_unix(key, True); /* Convert key to unix-codepage */
375 kbuf.dsize = strlen(key)+1;
377 if (tdb_delete(tdb, kbuf) != 0) {
378 *ret = ERROR_NOT_ENOUGH_MEMORY;
385 /****************************************************************************
387 ****************************************************************************/
388 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
392 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
394 DEBUG(106, ("[%s]\n", form_name));
395 for (n=0; n<count; n++)
397 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
398 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
402 if (n==count) return;
404 (*list)[n].flag=form->flags;
405 (*list)[n].width=form->size_x;
406 (*list)[n].length=form->size_y;
407 (*list)[n].left=form->left;
408 (*list)[n].top=form->top;
409 (*list)[n].right=form->right;
410 (*list)[n].bottom=form->bottom;
413 /****************************************************************************
414 get the nt drivers list
416 traverse the database and look-up the matching names
417 ****************************************************************************/
418 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
423 TDB_DATA kbuf, newkey;
425 get_short_archi(short_archi, architecture);
426 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
428 for (kbuf = tdb_firstkey(tdb);
430 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
431 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
433 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
436 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
443 /****************************************************************************
444 function to do the mapping between the long architecture name and
446 ****************************************************************************/
447 BOOL get_short_archi(char *short_archi, char *long_archi)
454 struct table archi_table[]=
456 {"Windows 4.0", "WIN40" },
457 {"Windows NT x86", "W32X86" },
458 {"Windows NT R4000", "W32MIPS" },
459 {"Windows NT Alpha_AXP", "W32ALPHA" },
460 {"Windows NT PowerPC", "W32PPC" },
466 DEBUG(107,("Getting architecture dependant directory\n"));
469 } while ( (archi_table[i].long_archi!=NULL ) &&
470 StrCaseCmp(long_archi, archi_table[i].long_archi) );
472 if (archi_table[i].long_archi==NULL) {
473 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
477 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
479 DEBUGADD(108,("index: [%d]\n", i));
480 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
481 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
486 /****************************************************************************
487 Determine the correct cVersion associated with an architecture and driver
488 ****************************************************************************/
489 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
490 struct current_user *user, uint32 *perr)
496 char buf[PE_HEADER_SIZE];
501 files_struct *fsp = NULL;
505 connection_struct *conn;
509 /* If architecture is Windows 95/98, the version is always 0. */
510 if (strcmp(architecture, "WIN40") == 0) {
511 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
516 pass = sys_getpwuid(user->uid);
518 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
519 (unsigned int)user->uid ));
521 *perr = ERROR_ACCESS_DENIED;
526 /* connect to the print$ share under the same account as the user connected
528 fstrcpy(user_name, pass->pw_name );
529 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
531 /* Null password is ok - we are already an authenticated user... */
533 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
536 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
537 *perr = (uint32)ecode;
541 /* Save who we are - we are temporarily becoming the connection user. */
544 if (!become_user(conn, conn->vuid)) {
545 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
546 *perr = ERROR_ACCESS_DENIED;
551 /* Open the driver file (Portable Executable format) and determine the
552 * deriver the cversion. */
553 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
555 unix_convert(driverpath,conn,NULL,&bad_path,&st);
557 fsp = open_file_shared(conn, driverpath, &st,
558 SET_OPEN_MODE(DOS_OPEN_RDONLY),
559 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
560 0, 0, &access_mode, &action);
562 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
564 *perr = ERROR_ACCESS_DENIED;
568 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
569 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
570 driverpath, byte_count));
571 *perr = NT_STATUS_FILE_INVALID;
575 /* Is this really a DOS header? */
576 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
577 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
578 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
579 *perr = NT_STATUS_FILE_INVALID;
583 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
584 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
585 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
587 *perr = NT_STATUS_FILE_INVALID;
591 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
592 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
593 driverpath, byte_count));
594 *perr = NT_STATUS_FILE_INVALID;
598 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
599 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
600 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
602 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
603 case 4: cversion = 2; break; /* Win NT 4 */
604 case 5: cversion = 3; break; /* Win 2000 */
606 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
607 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
608 *perr = NT_STATUS_FILE_INVALID;
612 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
613 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
614 *perr = NT_STATUS_FILE_INVALID;
618 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
619 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
621 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
622 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
623 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
625 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
626 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
627 *perr = NT_STATUS_FILE_INVALID;
631 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
632 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
633 *perr = NT_STATUS_FILE_INVALID;
638 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
639 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
640 *perr = NT_STATUS_FILE_INVALID;
644 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
645 driverpath, cversion));
647 fsp->conn->vfs_ops.close(fsp, fsp->fd);
649 close_cnum(conn, user->vuid);
657 fsp->conn->vfs_ops.close(fsp, fsp->fd);
661 close_cnum(conn, user->vuid);
666 /****************************************************************************
667 ****************************************************************************/
668 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
669 struct current_user *user)
671 fstring architecture;
677 /* clean up the driver name.
678 * we can get .\driver.dll
679 * or worse c:\windows\system\driver.dll !
681 /* using an intermediate string to not have overlaping memcpy()'s */
682 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
683 fstrcpy(new_name, p+1);
684 fstrcpy(driver->driverpath, new_name);
687 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
688 fstrcpy(new_name, p+1);
689 fstrcpy(driver->datafile, new_name);
692 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
693 fstrcpy(new_name, p+1);
694 fstrcpy(driver->configfile, new_name);
697 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
698 fstrcpy(new_name, p+1);
699 fstrcpy(driver->helpfile, new_name);
702 if (driver->dependentfiles) {
703 for (i=0; *driver->dependentfiles[i]; i++) {
704 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
705 fstrcpy(new_name, p+1);
706 fstrcpy(driver->dependentfiles[i], new_name);
711 get_short_archi(architecture, driver->environment);
713 /* jfm:7/16/2000 the client always sends the cversion=0.
714 * The server should check which version the driver is by reading
715 * the PE header of driver->driverpath.
717 * For Windows 95/98 the version is 0 (so the value sent is correct)
718 * For Windows NT (the architecture doesn't matter)
720 * NT 3.5/3.51: cversion=1
724 if ((driver->cversion = get_correct_cversion( architecture,
725 driver->driverpath, user, &err)) == -1)
728 return NT_STATUS_NO_PROBLEMO;
731 /****************************************************************************
732 ****************************************************************************/
733 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
734 struct current_user *user)
736 fstring architecture;
742 /* clean up the driver name.
743 * we can get .\driver.dll
744 * or worse c:\windows\system\driver.dll !
746 /* using an intermediate string to not have overlaping memcpy()'s */
747 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
748 fstrcpy(new_name, p+1);
749 fstrcpy(driver->driverpath, new_name);
752 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
753 fstrcpy(new_name, p+1);
754 fstrcpy(driver->datafile, new_name);
757 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
758 fstrcpy(new_name, p+1);
759 fstrcpy(driver->configfile, new_name);
762 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
763 fstrcpy(new_name, p+1);
764 fstrcpy(driver->helpfile, new_name);
767 if (driver->dependentfiles) {
768 for (i=0; *driver->dependentfiles[i]; i++) {
769 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
770 fstrcpy(new_name, p+1);
771 fstrcpy(driver->dependentfiles[i], new_name);
776 get_short_archi(architecture, driver->environment);
778 /* jfm:7/16/2000 the client always sends the cversion=0.
779 * The server should check which version the driver is by reading
780 * the PE header of driver->driverpath.
782 * For Windows 95/98 the version is 0 (so the value sent is correct)
783 * For Windows NT (the architecture doesn't matter)
785 * NT 3.5/3.51: cversion=1
789 if ((driver->version = get_correct_cversion(architecture,
790 driver->driverpath, user, &err)) == -1)
793 return NT_STATUS_NO_PROBLEMO;
796 /****************************************************************************
797 ****************************************************************************/
798 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
799 uint32 level, struct current_user *user)
804 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
805 driver=driver_abstract.info_3;
806 return clean_up_driver_struct_level_3(driver, user);
810 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
811 driver=driver_abstract.info_6;
812 return clean_up_driver_struct_level_6(driver, user);
815 return ERROR_INVALID_PARAMETER;
819 /****************************************************************************
820 This function sucks and should be replaced. JRA.
821 ****************************************************************************/
823 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
825 dst->cversion = src->version;
827 fstrcpy( dst->name, src->name);
828 fstrcpy( dst->environment, src->environment);
829 fstrcpy( dst->driverpath, src->driverpath);
830 fstrcpy( dst->datafile, src->datafile);
831 fstrcpy( dst->configfile, src->configfile);
832 fstrcpy( dst->helpfile, src->helpfile);
833 fstrcpy( dst->monitorname, src->monitorname);
834 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
835 dst->dependentfiles = src->dependentfiles;
838 #if 0 /* Debugging function */
840 static char* ffmt(unsigned char *c){
842 static char ffmt_str[17];
844 for (i=0; i<16; i++) {
845 if ((c[i] < ' ') || (c[i] > '~'))
856 /****************************************************************************
857 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
858 There are two case to be covered here: PE (Portable Executable) and NE (New
859 Executable) files. Both files support the same INFO structure, but PE files
860 store the signature in unicode, and NE files store it as !unicode.
861 ****************************************************************************/
862 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
869 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
870 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
871 fname, PE_HEADER_SIZE));
875 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
876 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
877 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
879 goto no_version_info;
882 /* Is this really a DOS header? */
883 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
884 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
885 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
886 goto no_version_info;
889 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
890 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
891 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
893 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
894 goto no_version_info;
897 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
898 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
900 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
901 goto no_version_info;
904 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
905 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
907 int section_table_bytes;
909 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
910 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
911 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
912 /* At this point, we assume the file is in error. It still could be somthing
913 * else besides a PE file, but it unlikely at this point.
918 /* get the section table */
919 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
920 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
922 if ((buf=malloc(section_table_bytes)) == NULL) {
923 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
924 fname, section_table_bytes));
928 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
929 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
934 /* Iterate the section table looking for the resource section ".rsrc" */
935 for (i = 0; i < num_sections; i++) {
936 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
938 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
939 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
940 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
943 if ((buf=malloc(section_bytes)) == NULL) {
944 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
945 fname, section_bytes));
949 /* Seek to the start of the .rsrc section info */
950 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
951 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
956 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
957 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
962 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
963 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
964 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
965 /* Align to next long address */
966 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
968 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
969 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
970 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
972 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
973 fname, *major, *minor,
974 (*major>>16)&0xffff, *major&0xffff,
975 (*minor>>16)&0xffff, *minor&0xffff));
984 /* Version info not found, fall back to origin date/time */
985 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
989 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
990 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
991 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
992 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
993 /* At this point, we assume the file is in error. It still could be somthing
994 * else besides a NE file, but it unlikely at this point. */
998 /* Allocate a bit more space to speed up things */
1000 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
1001 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1002 fname, PE_HEADER_SIZE));
1006 /* This is a HACK! I got tired of trying to sort through the messy
1007 * 'NE' file format. If anyone wants to clean this up please have at
1008 * it, but this works. 'NE' files will eventually fade away. JRR */
1009 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1010 /* Cover case that should not occur in a well formed 'NE' .dll file */
1011 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1013 for(i=0; i<byte_count; i++) {
1014 /* Fast skip past data that can't possibly match */
1015 if (buf[i] != 'V') continue;
1017 /* Potential match data crosses buf boundry, move it to beginning
1018 * of buf, and fill the buf with as much as it will hold. */
1019 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1022 memcpy(buf, &buf[i], byte_count-i);
1023 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1024 (byte_count-i))) < 0) {
1026 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1031 byte_count = bc + (byte_count - i);
1032 if (byte_count<VS_VERSION_INFO_SIZE) break;
1037 /* Check that the full signature string and the magic number that
1038 * follows exist (not a perfect solution, but the chances that this
1039 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1040 * twice, as it is simpler to read the code. */
1041 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1042 /* Compute skip alignment to next long address */
1043 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1044 sizeof(VS_SIGNATURE)) & 3;
1045 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1047 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1048 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1049 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1050 fname, *major, *minor,
1051 (*major>>16)&0xffff, *major&0xffff,
1052 (*minor>>16)&0xffff, *minor&0xffff));
1059 /* Version info not found, fall back to origin date/time */
1060 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1065 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1066 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1067 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1078 /****************************************************************************
1079 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1080 share one or more files. During the MS installation process files are checked
1081 to insure that only a newer version of a shared file is installed over an
1082 older version. There are several possibilities for this comparison. If there
1083 is no previous version, the new one is newer (obviously). If either file is
1084 missing the version info structure, compare the creation date (on Unix use
1085 the modification date). Otherwise chose the numerically larger version number.
1086 ****************************************************************************/
1087 static int file_version_is_newer(connection_struct *conn, fstring new_file,
1090 BOOL use_version = True;
1095 time_t new_create_time;
1099 time_t old_create_time;
1103 files_struct *fsp = NULL;
1105 SMB_STRUCT_STAT stat_buf;
1109 ZERO_STRUCT(stat_buf);
1110 new_create_time = (time_t)0;
1111 old_create_time = (time_t)0;
1113 /* Get file version info (if available) for previous file (if it exists) */
1114 pstrcpy(filepath, old_file);
1116 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1118 fsp = open_file_shared(conn, filepath, &stat_buf,
1119 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1120 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1121 0, 0, &access_mode, &action);
1123 /* Old file not found, so by definition new file is in fact newer */
1124 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1129 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1130 if (ret == -1) goto error_exit;
1133 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1135 use_version = False;
1136 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1137 old_create_time = st.st_mtime;
1138 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1141 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1145 /* Get file version info (if available) for new file */
1146 pstrcpy(filepath, new_file);
1147 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1149 fsp = open_file_shared(conn, filepath, &stat_buf,
1150 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1151 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1152 0, 0, &access_mode, &action);
1154 /* New file not found, this shouldn't occur if the caller did its job */
1155 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1160 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1161 if (ret == -1) goto error_exit;
1164 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1166 use_version = False;
1167 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1168 new_create_time = st.st_mtime;
1169 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1172 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1176 /* Compare versions and choose the larger version number */
1177 if (new_major > old_major ||
1178 (new_major == old_major && new_minor > old_minor)) {
1180 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1184 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1189 /* Compare modification time/dates and choose the newest time/date */
1190 if (new_create_time > old_create_time) {
1191 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1195 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1204 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1209 /****************************************************************************
1210 ****************************************************************************/
1211 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1213 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1214 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1215 fstring architecture;
1221 connection_struct *conn;
1224 struct passwd *pass;
1230 memset(inbuf, '\0', sizeof(inbuf));
1231 memset(outbuf, '\0', sizeof(outbuf));
1234 driver=driver_abstract.info_3;
1235 else if (level==6) {
1236 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1237 driver = &converted_driver;
1239 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1243 get_short_archi(architecture, driver->environment);
1246 pass = sys_getpwuid(user->uid);
1248 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1249 (unsigned int)user->uid ));
1255 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1256 fstrcpy(user_name, pass->pw_name );
1257 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1259 /* Null password is ok - we are already an authenticated user... */
1261 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1264 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1265 *perr = (uint32)ecode;
1270 * Save who we are - we are temporarily becoming the connection user.
1275 if (!become_user(conn, conn->vuid)) {
1276 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1282 * make the directories version and version\driver_name
1283 * under the architecture directory.
1285 DEBUG(5,("Creating first directory\n"));
1286 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1287 mkdir_internal(conn, inbuf, outbuf, new_dir);
1289 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1290 * listed for this driver which has already been moved, skip it (note:
1291 * drivers may list the same file name several times. Then check if the
1292 * file already exists in archi\cversion\, if so, check that the version
1293 * info (or time stamps if version info is unavailable) is newer (or the
1294 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1295 * Otherwise, delete the file.
1297 * If a file is not moved to archi\cversion\ because of an error, all the
1298 * rest of the 'unmoved' driver files are removed from archi\. If one or
1299 * more of the driver's files was already moved to archi\cversion\, it
1300 * potentially leaves the driver in a partially updated state. Version
1301 * trauma will most likely occur if an client attempts to use any printer
1302 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1303 * done is appropriate... later JRR
1306 DEBUG(5,("Moving files now !\n"));
1308 if (driver->driverpath && strlen(driver->driverpath)) {
1309 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1310 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1311 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1312 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1313 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1314 new_name, old_name));
1315 *perr = (uint32)SVAL(outbuf,smb_err);
1316 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1321 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1324 if (driver->datafile && strlen(driver->datafile)) {
1325 if (!strequal(driver->datafile, driver->driverpath)) {
1326 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1327 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1328 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1329 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1330 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1331 new_name, old_name));
1332 *perr = (uint32)SVAL(outbuf,smb_err);
1333 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1338 unlink_internals(conn, inbuf, outbuf, 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 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1349 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1350 new_name, old_name));
1351 *perr = (uint32)SVAL(outbuf,smb_err);
1352 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1357 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1361 if (driver->helpfile && strlen(driver->helpfile)) {
1362 if (!strequal(driver->helpfile, driver->driverpath) &&
1363 !strequal(driver->helpfile, driver->datafile) &&
1364 !strequal(driver->helpfile, driver->configfile)) {
1365 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1366 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1367 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1368 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1369 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1370 new_name, old_name));
1371 *perr = (uint32)SVAL(outbuf,smb_err);
1372 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1377 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1381 if (driver->dependentfiles) {
1382 for (i=0; *driver->dependentfiles[i]; i++) {
1383 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1384 !strequal(driver->dependentfiles[i], driver->datafile) &&
1385 !strequal(driver->dependentfiles[i], driver->configfile) &&
1386 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1388 for (j=0; j < i; j++) {
1389 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1394 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1395 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1396 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1397 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1398 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1399 new_name, old_name));
1400 *perr = (uint32)SVAL(outbuf,smb_err);
1401 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1406 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1412 close_cnum(conn, user->vuid);
1415 return ver == -1 ? False : True;
1418 /****************************************************************************
1419 ****************************************************************************/
1420 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1423 fstring architecture;
1429 TDB_DATA kbuf, dbuf;
1431 get_short_archi(architecture, driver->environment);
1433 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1434 * \\server is added in the rpc server layer.
1435 * It does make sense to NOT store the server's name in the printer TDB.
1438 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1440 /* .inf files do not always list a file for each of the four standard files.
1441 * Don't prepend a path to a null filename, or client claims:
1442 * "The server on which the printer resides does not have a suitable
1443 * <printer driver name> printer driver installed. Click OK if you
1444 * wish to install the driver on your local machine."
1446 if (strlen(driver->driverpath)) {
1447 fstrcpy(temp_name, driver->driverpath);
1448 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1451 if (strlen(driver->datafile)) {
1452 fstrcpy(temp_name, driver->datafile);
1453 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1456 if (strlen(driver->configfile)) {
1457 fstrcpy(temp_name, driver->configfile);
1458 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1461 if (strlen(driver->helpfile)) {
1462 fstrcpy(temp_name, driver->helpfile);
1463 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1466 if (driver->dependentfiles) {
1467 for (i=0; *driver->dependentfiles[i]; i++) {
1468 fstrcpy(temp_name, driver->dependentfiles[i]);
1469 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1473 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1474 dos_to_unix(key, True); /* Convert key to unix-codepage */
1476 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1483 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1486 driver->environment,
1491 driver->monitorname,
1492 driver->defaultdatatype);
1494 if (driver->dependentfiles) {
1495 for (i=0; *driver->dependentfiles[i]; i++) {
1496 len += tdb_pack(buf+len, buflen-len, "f",
1497 driver->dependentfiles[i]);
1501 if (len != buflen) {
1502 buf = (char *)Realloc(buf, len);
1509 kbuf.dsize = strlen(key)+1;
1513 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1516 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1522 /****************************************************************************
1523 ****************************************************************************/
1524 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1526 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1529 info3.cversion = driver->version;
1530 fstrcpy(info3.name,driver->name);
1531 fstrcpy(info3.environment,driver->environment);
1532 fstrcpy(info3.driverpath,driver->driverpath);
1533 fstrcpy(info3.datafile,driver->datafile);
1534 fstrcpy(info3.configfile,driver->configfile);
1535 fstrcpy(info3.helpfile,driver->helpfile);
1536 fstrcpy(info3.monitorname,driver->monitorname);
1537 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1538 info3.dependentfiles = driver->dependentfiles;
1540 return add_a_printer_driver_3(&info3);
1544 /****************************************************************************
1545 ****************************************************************************/
1546 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1548 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1552 fstrcpy(info.name, in_prt);
1553 fstrcpy(info.defaultdatatype, "RAW");
1555 fstrcpy(info.driverpath, "");
1556 fstrcpy(info.datafile, "");
1557 fstrcpy(info.configfile, "");
1558 fstrcpy(info.helpfile, "");
1560 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1561 return ERROR_NOT_ENOUGH_MEMORY;
1563 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1564 fstrcpy(info.dependentfiles[0], "");
1566 *info_ptr = memdup(&info, sizeof(info));
1571 /****************************************************************************
1572 ****************************************************************************/
1573 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1575 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1576 TDB_DATA kbuf, dbuf;
1577 fstring architecture;
1582 ZERO_STRUCT(driver);
1584 get_short_archi(architecture, in_arch);
1586 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1588 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1591 kbuf.dsize = strlen(key)+1;
1593 dbuf = tdb_fetch(tdb, kbuf);
1595 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1597 if (!dbuf.dptr) return 5;
1599 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1608 driver.defaultdatatype);
1611 while (len < dbuf.dsize) {
1612 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1613 sizeof(fstring)*(i+2));
1614 if (driver.dependentfiles == NULL)
1617 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1618 &driver.dependentfiles[i]);
1621 if (driver.dependentfiles != NULL)
1622 fstrcpy(driver.dependentfiles[i], "");
1624 safe_free(dbuf.dptr);
1626 if (len != dbuf.dsize) {
1627 if (driver.dependentfiles != NULL)
1628 safe_free(driver.dependentfiles);
1630 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1633 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1638 /****************************************************************************
1639 ****************************************************************************/
1640 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1642 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1648 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1649 DEBUG(10,("driver key: [%s]\n", key));
1652 kbuf.dsize = strlen(key)+1;
1653 if (!tdb_exists(tdb, kbuf)) return False;
1656 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1658 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1659 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1660 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1661 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1662 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1663 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1664 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1666 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1667 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1668 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1670 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1671 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1672 pstrcat(line, info3->configfile);
1674 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1675 pstrcat(line, info3->datafile);
1677 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1678 pstrcat(line, info3->helpfile);
1680 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1681 pstrcat(line, info3->monitorname);
1683 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1686 for (i=0; info3->dependentfiles &&
1687 *info3->dependentfiles[i]; i++) {
1688 if (i) pstrcat(line, ","); /* don't end in a "," */
1689 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1690 pstrcat(line, info3->dependentfiles[i]);
1698 /****************************************************************************
1699 debugging function, dump at level 6 the struct in the logs
1700 ****************************************************************************/
1701 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1704 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1707 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1713 if (driver.info_3 == NULL)
1716 info3=driver.info_3;
1718 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1719 DEBUGADD(106,("name:[%s]\n", info3->name));
1720 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1721 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1722 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1723 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1724 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1725 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1726 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1728 for (i=0; info3->dependentfiles &&
1729 *info3->dependentfiles[i]; i++) {
1730 DEBUGADD(106,("dependentfile:[%s]\n",
1731 info3->dependentfiles[i]));
1738 DEBUGADD(1,("Level not implemented\n"));
1746 /****************************************************************************
1747 ****************************************************************************/
1748 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1752 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1754 if (!nt_devmode) return len;
1756 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1757 nt_devmode->devicename,
1758 nt_devmode->formname,
1760 nt_devmode->specversion,
1761 nt_devmode->driverversion,
1763 nt_devmode->driverextra,
1764 nt_devmode->orientation,
1765 nt_devmode->papersize,
1766 nt_devmode->paperlength,
1767 nt_devmode->paperwidth,
1770 nt_devmode->defaultsource,
1771 nt_devmode->printquality,
1774 nt_devmode->yresolution,
1775 nt_devmode->ttoption,
1776 nt_devmode->collate,
1777 nt_devmode->logpixels,
1780 nt_devmode->bitsperpel,
1781 nt_devmode->pelswidth,
1782 nt_devmode->pelsheight,
1783 nt_devmode->displayflags,
1784 nt_devmode->displayfrequency,
1785 nt_devmode->icmmethod,
1786 nt_devmode->icmintent,
1787 nt_devmode->mediatype,
1788 nt_devmode->dithertype,
1789 nt_devmode->reserved1,
1790 nt_devmode->reserved2,
1791 nt_devmode->panningwidth,
1792 nt_devmode->panningheight,
1793 nt_devmode->private);
1796 if (nt_devmode->private) {
1797 len += tdb_pack(buf+len, buflen-len, "B",
1798 nt_devmode->driverextra,
1799 nt_devmode->private);
1802 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1807 /****************************************************************************
1808 ****************************************************************************/
1809 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1813 while (param != NULL) {
1814 len += tdb_pack(buf+len, buflen-len, "pfdB",
1823 len += tdb_pack(buf+len, buflen-len, "p", param);
1829 /****************************************************************************
1830 delete a printer - this just deletes the printer info file, any open
1831 handles are not affected
1832 ****************************************************************************/
1833 uint32 del_a_printer(char *sharename)
1838 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1839 dos_to_unix(key, True); /* Convert key to unix-codepage */
1842 kbuf.dsize=strlen(key)+1;
1844 tdb_delete(tdb, kbuf);
1848 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1849 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1850 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1851 /****************************************************************************
1852 ****************************************************************************/
1853 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1857 int buflen, len, ret;
1858 TDB_DATA kbuf, dbuf;
1861 * in addprinter: no servername and the printer is the name
1862 * in setprinter: servername is \\server
1863 * and printer is \\server\\printer
1865 * Samba manages only local printers.
1866 * we currently don't support things like path=\\other_server\printer
1869 if (info->servername[0]!='\0') {
1870 trim_string(info->printername, info->servername, NULL);
1871 trim_string(info->printername, "\\", NULL);
1872 info->servername[0]='\0';
1876 * JFM: one day I'll forget.
1877 * below that's info->portname because that's the SAMBA sharename
1878 * and I made NT 'thinks' it's the portname
1879 * the info->sharename is the thing you can name when you add a printer
1880 * that's the short-name when you create shared printer for 95/98
1881 * So I've made a limitation in SAMBA: you can only have 1 printer model
1882 * behind a SAMBA share.
1890 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1893 info->default_priority,
1910 info->printprocessor,
1914 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1916 len += pack_specifics(info->specific, buf+len, buflen-len);
1918 if (buflen != len) {
1919 buf = (char *)Realloc(buf, len);
1925 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1926 dos_to_unix(key, True); /* Convert key to unix-codepage */
1929 kbuf.dsize = strlen(key)+1;
1933 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1936 DEBUG(8, ("error updating printer to tdb on disk\n"));
1940 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1941 info->sharename, info->drivername, info->portname, len));
1947 /****************************************************************************
1948 ****************************************************************************/
1949 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1951 NT_PRINTER_PARAM *current;
1953 DEBUG(108,("add_a_specific_param\n"));
1955 (*param)->next=NULL;
1957 if (info_2->specific == NULL)
1959 info_2->specific=*param;
1963 current=info_2->specific;
1964 while (current->next != NULL) {
1965 current=current->next;
1967 current->next=*param;
1973 /****************************************************************************
1974 ****************************************************************************/
1975 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1977 NT_PRINTER_PARAM *current;
1978 NT_PRINTER_PARAM *previous;
1980 current=info_2->specific;
1983 if (current==NULL) return (False);
1985 if ( !strcmp(current->value, param->value) &&
1986 (strlen(current->value)==strlen(param->value)) ) {
1987 DEBUG(109,("deleting first value\n"));
1988 info_2->specific=current->next;
1989 safe_free(current->data);
1991 DEBUG(109,("deleted first value\n"));
1995 current=previous->next;
1997 while ( current!=NULL ) {
1998 if (!strcmp(current->value, param->value) &&
1999 strlen(current->value)==strlen(param->value) ) {
2000 DEBUG(109,("deleting current value\n"));
2001 previous->next=current->next;
2002 safe_free(current->data);
2004 DEBUG(109,("deleted current value\n"));
2008 previous=previous->next;
2009 current=current->next;
2014 /****************************************************************************
2015 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2016 ****************************************************************************/
2017 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2019 NT_PRINTER_PARAM *param = *param_ptr;
2024 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2027 safe_free(param->data);
2033 /****************************************************************************
2034 Malloc and return an NT devicemode.
2035 ****************************************************************************/
2037 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2040 * should I init this ones ???
2041 nt_devmode->devicename
2045 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2047 if (nt_devmode == NULL) {
2048 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2052 ZERO_STRUCTP(nt_devmode);
2054 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2055 fstrcpy(nt_devmode->devicename, adevice);
2057 fstrcpy(nt_devmode->formname, "Letter");
2059 nt_devmode->specversion = 0x0401;
2060 nt_devmode->driverversion = 0x0400;
2061 nt_devmode->size = 0x00DC;
2062 nt_devmode->driverextra = 0x0000;
2063 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2064 DEFAULTSOURCE | COPIES | SCALE |
2065 PAPERSIZE | ORIENTATION;
2066 nt_devmode->orientation = 1;
2067 nt_devmode->papersize = PAPER_LETTER;
2068 nt_devmode->paperlength = 0;
2069 nt_devmode->paperwidth = 0;
2070 nt_devmode->scale = 0x64;
2071 nt_devmode->copies = 01;
2072 nt_devmode->defaultsource = BIN_FORMSOURCE;
2073 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2074 nt_devmode->color = COLOR_MONOCHROME;
2075 nt_devmode->duplex = DUP_SIMPLEX;
2076 nt_devmode->yresolution = 0;
2077 nt_devmode->ttoption = TT_SUBDEV;
2078 nt_devmode->collate = COLLATE_FALSE;
2079 nt_devmode->icmmethod = 0;
2080 nt_devmode->icmintent = 0;
2081 nt_devmode->mediatype = 0;
2082 nt_devmode->dithertype = 0;
2084 /* non utilisés par un driver d'imprimante */
2085 nt_devmode->logpixels = 0;
2086 nt_devmode->bitsperpel = 0;
2087 nt_devmode->pelswidth = 0;
2088 nt_devmode->pelsheight = 0;
2089 nt_devmode->displayflags = 0;
2090 nt_devmode->displayfrequency = 0;
2091 nt_devmode->reserved1 = 0;
2092 nt_devmode->reserved2 = 0;
2093 nt_devmode->panningwidth = 0;
2094 nt_devmode->panningheight = 0;
2096 nt_devmode->private = NULL;
2100 /****************************************************************************
2101 Deepcopy an NT devicemode.
2102 ****************************************************************************/
2104 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2106 NT_DEVICEMODE *new_nt_devicemode = NULL;
2108 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2109 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2113 new_nt_devicemode->private = NULL;
2114 if (nt_devicemode->private != NULL) {
2115 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2116 safe_free(new_nt_devicemode);
2117 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2122 return new_nt_devicemode;
2125 /****************************************************************************
2126 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2127 ****************************************************************************/
2129 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2131 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2133 if(nt_devmode == NULL)
2136 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2138 if(nt_devmode->private)
2139 safe_free(nt_devmode->private);
2141 safe_free(nt_devmode);
2142 *devmode_ptr = NULL;
2145 /****************************************************************************
2146 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2147 ****************************************************************************/
2148 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2150 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2151 NT_PRINTER_PARAM *param_ptr;
2156 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2158 free_nt_devicemode(&info->devmode);
2160 for(param_ptr = info->specific; param_ptr; ) {
2161 NT_PRINTER_PARAM *tofree = param_ptr;
2163 param_ptr = param_ptr->next;
2164 free_nt_printer_param(&tofree);
2167 safe_free(*info_ptr);
2172 /****************************************************************************
2173 ****************************************************************************/
2174 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2178 NT_DEVICEMODE devmode;
2180 ZERO_STRUCT(devmode);
2182 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2184 if (!*nt_devmode) return len;
2186 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2190 &devmode.specversion,
2191 &devmode.driverversion,
2193 &devmode.driverextra,
2194 &devmode.orientation,
2196 &devmode.paperlength,
2197 &devmode.paperwidth,
2200 &devmode.defaultsource,
2201 &devmode.printquality,
2204 &devmode.yresolution,
2210 &devmode.bitsperpel,
2212 &devmode.pelsheight,
2213 &devmode.displayflags,
2214 &devmode.displayfrequency,
2218 &devmode.dithertype,
2221 &devmode.panningwidth,
2222 &devmode.panningheight,
2225 if (devmode.private) {
2226 /* the len in tdb_unpack is an int value and
2227 * devmode.driverextra is only a short
2229 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2230 devmode.driverextra=(uint16)extra_len;
2232 /* check to catch an invalid TDB entry so we don't segfault */
2233 if (devmode.driverextra == 0) {
2234 devmode.private = NULL;
2238 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2240 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2241 if (devmode.private)
2242 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2247 /****************************************************************************
2248 ****************************************************************************/
2249 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2252 NT_PRINTER_PARAM param, *p;
2257 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2260 len += tdb_unpack(buf+len, buflen-len, "fdB",
2266 *list = memdup(¶m, sizeof(param));
2268 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2274 static void map_to_os2_driver(fstring drivername)
2276 static BOOL initialised=False;
2277 static fstring last_from,last_to;
2278 char *mapfile = lp_os2_driver_map();
2279 char **lines = NULL;
2283 if (!strlen(drivername))
2290 *last_from = *last_to = 0;
2294 if (strequal(drivername,last_from)) {
2295 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2296 fstrcpy(drivername,last_to);
2300 lines = file_lines_load(mapfile, &numlines, True);
2301 if (numlines == 0) {
2302 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2306 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2308 for( i = 0; i < numlines; i++) {
2309 char *nt_name = lines[i];
2310 char *os2_name = strchr(nt_name,'=');
2317 while (isspace(*nt_name))
2320 if (!*nt_name || strchr("#;",*nt_name))
2324 int l = strlen(nt_name);
2325 while (l && isspace(nt_name[l-1])) {
2331 while (isspace(*os2_name))
2335 int l = strlen(os2_name);
2336 while (l && isspace(os2_name[l-1])) {
2342 if (strequal(nt_name,drivername)) {
2343 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2344 fstrcpy(last_from,drivername);
2345 fstrcpy(last_to,os2_name);
2346 fstrcpy(drivername,os2_name);
2347 file_lines_free(lines);
2352 file_lines_free(lines);
2355 /****************************************************************************
2356 get a default printer info 2 struct
2357 ****************************************************************************/
2358 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2360 extern pstring global_myname;
2362 NT_PRINTER_INFO_LEVEL_2 info;
2366 snum = lp_servicenumber(sharename);
2368 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2369 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2370 global_myname, sharename);
2371 fstrcpy(info.sharename, sharename);
2372 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2373 fstrcpy(info.drivername, lp_printerdriver(snum));
2376 if (!*info.drivername)
2377 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2379 /* by setting the driver name to an empty string, a local NT admin
2380 can now run the **local** APW to install a local printer driver
2381 for a Samba shared printer in 2.2. Without this, drivers **must** be
2382 installed on the Samba server for NT clients --jerry */
2383 if (!*info.drivername)
2384 fstrcpy(info.drivername, "");
2388 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2390 pstrcpy(info.comment, "");
2391 fstrcpy(info.printprocessor, "winprint");
2392 fstrcpy(info.datatype, "RAW");
2394 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2395 | PRINTER_ATTRIBUTE_LOCAL \
2396 | PRINTER_ATTRIBUTE_RAW_ONLY \
2397 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2399 info.starttime = 0; /* Minutes since 12:00am GMT */
2400 info.untiltime = 0; /* Minutes since 12:00am GMT */
2402 info.default_priority = 1;
2403 info.setuptime = (uint32)time(NULL);
2405 #if 1 /* JRA - NO NOT CHANGE ! */
2406 info.devmode = NULL;
2409 * We should not return a default devicemode, as this causes
2410 * Win2K to not send the correct one on PCL drivers. It needs to
2411 * see a null devicemode so it can then overwrite the devicemode
2412 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2414 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2418 /* This will get the current RPC talloc context, but we should be
2419 passing this as a parameter... fixme... JRA ! */
2421 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2424 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2426 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2435 free_nt_devicemode(&info.devmode);
2439 /****************************************************************************
2440 ****************************************************************************/
2441 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2444 NT_PRINTER_INFO_LEVEL_2 info;
2446 TDB_DATA kbuf, dbuf;
2447 fstring printername;
2451 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2452 dos_to_unix(key, True); /* Convert key to unix-codepage */
2455 kbuf.dsize = strlen(key)+1;
2457 dbuf = tdb_fetch(tdb, kbuf);
2459 return get_a_printer_2_default(info_ptr, sharename);
2461 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2464 &info.default_priority,
2481 info.printprocessor,
2485 /* Samba has to have shared raw drivers. */
2486 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2488 /* Restore the stripped strings. */
2489 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2490 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2492 fstrcpy(info.printername, printername);
2494 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2495 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2497 /* This will get the current RPC talloc context, but we should be
2498 passing this as a parameter... fixme... JRA ! */
2500 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2502 /* Fix for OS/2 drivers. */
2504 if (get_remote_arch() == RA_OS2)
2505 map_to_os2_driver(info.drivername);
2507 safe_free(dbuf.dptr);
2508 *info_ptr=memdup(&info, sizeof(info));
2510 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2511 sharename, info.printername, info.drivername));
2517 /****************************************************************************
2518 debugging function, dump at level 6 the struct in the logs
2519 ****************************************************************************/
2520 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2523 NT_PRINTER_INFO_LEVEL_2 *info2;
2525 DEBUG(106,("Dumping printer at level [%d]\n", level));
2531 if (printer.info_2 == NULL)
2535 info2=printer.info_2;
2537 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2538 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2539 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2540 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2541 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2542 DEBUGADD(106,("status:[%d]\n", info2->status));
2543 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2544 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2545 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2546 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2547 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2549 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2550 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2551 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2552 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2553 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2554 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2555 DEBUGADD(106,("location:[%s]\n", info2->location));
2556 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2557 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2558 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2559 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2565 DEBUGADD(1,("Level not implemented\n"));
2573 /****************************************************************************
2574 Get the parameters we can substitute in an NT print job.
2575 ****************************************************************************/
2577 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2579 NT_PRINTER_INFO_LEVEL *printer = NULL;
2581 **printername = **sharename = **portname = '\0';
2583 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2586 fstrcpy(*printername, printer->info_2->printername);
2587 fstrcpy(*sharename, printer->info_2->sharename);
2588 fstrcpy(*portname, printer->info_2->portname);
2590 free_a_printer(&printer, 2);
2594 * The function below are the high level ones.
2595 * only those ones must be called from the spoolss code.
2599 /****************************************************************************
2600 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2601 ****************************************************************************/
2603 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2607 dump_a_printer(printer, level);
2613 printer.info_2->c_setprinter++;
2614 result=update_a_printer_2(printer.info_2);
2625 /****************************************************************************
2626 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2627 We split this out from mod_a_printer as it updates the id's and timestamps.
2628 ****************************************************************************/
2630 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2634 dump_a_printer(printer, level);
2641 * Update the changestamp.
2642 * Note we must *not* do this in mod_a_printer().
2645 time_t time_unix = time(NULL);
2646 unix_to_nt_time(&time_nt, time_unix);
2647 if (printer.info_2->changeid==time_nt.low)
2648 printer.info_2->changeid++;
2650 printer.info_2->changeid=time_nt.low;
2652 printer.info_2->c_setprinter++;
2654 result=update_a_printer_2(printer.info_2);
2665 /****************************************************************************
2666 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2667 ****************************************************************************/
2669 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2672 NT_PRINTER_INFO_LEVEL *printer = NULL;
2676 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2682 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2683 DEBUG(0,("get_a_printer: malloc fail.\n"));
2686 ZERO_STRUCTP(printer);
2687 result=get_a_printer_2(&printer->info_2, sharename);
2689 dump_a_printer(*printer, level);
2690 *pp_printer = printer;
2701 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2706 /****************************************************************************
2707 Deletes a NT_PRINTER_INFO_LEVEL struct.
2708 ****************************************************************************/
2710 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2713 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2715 DEBUG(104,("freeing a printer at level [%d]\n", level));
2717 if (printer == NULL)
2724 if (printer->info_2 != NULL)
2726 free_nt_printer_info_level_2(&printer->info_2);
2745 /****************************************************************************
2746 ****************************************************************************/
2747 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2750 DEBUG(104,("adding a printer at level [%d]\n", level));
2751 dump_a_printer_driver(driver, level);
2757 result=add_a_printer_driver_3(driver.info_3);
2763 result=add_a_printer_driver_6(driver.info_6);
2773 /****************************************************************************
2774 ****************************************************************************/
2775 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2776 fstring printername, fstring architecture, uint32 version)
2784 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2793 dump_a_printer_driver(*driver, level);
2797 /****************************************************************************
2798 ****************************************************************************/
2799 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2807 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2808 if (driver.info_3 != NULL)
2810 info3=driver.info_3;
2811 safe_free(info3->dependentfiles);
2812 ZERO_STRUCTP(info3);
2824 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2825 if (driver.info_6 != NULL)
2827 info6=driver.info_6;
2828 safe_free(info6->dependentfiles);
2829 safe_free(info6->previousnames);
2830 ZERO_STRUCTP(info6);
2848 /****************************************************************************
2849 Determine whether or not a particular driver is currently assigned
2851 ****************************************************************************/
2852 BOOL printer_driver_in_use (char *arch, char *driver)
2854 TDB_DATA kbuf, newkey, dbuf;
2855 NT_PRINTER_INFO_LEVEL_2 info;
2861 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
2863 /* loop through the printers.tdb and check for the drivername */
2864 for (kbuf = tdb_firstkey(tdb); kbuf.dptr;
2865 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
2868 dbuf = tdb_fetch(tdb, kbuf);
2872 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
2875 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
2878 &info.default_priority,
2895 info.printprocessor,
2899 safe_free(dbuf.dptr);
2901 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
2902 info.printername, info.drivername));
2904 if (strcmp(info.drivername, driver) == 0)
2906 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
2907 info.printername, driver));
2911 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
2915 /* report that the driver is in use by default */
2919 /****************************************************************************
2920 Remove a printer driver from the TDB. This assumes that the the driver was
2921 previously looked up.
2922 ***************************************************************************/
2923 uint32 delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
2930 get_short_archi(arch, i->environment);
2931 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
2932 arch, i->cversion, i->name);
2933 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
2936 kbuf.dsize=strlen(key)+1;
2938 if (tdb_delete(tdb, kbuf) == -1) {
2939 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
2940 return NT_STATUS_ACCESS_VIOLATION;
2943 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
2946 return NT_STATUS_NO_PROBLEMO;
2948 /****************************************************************************
2949 ****************************************************************************/
2950 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2951 fstring value, uint8 **data, uint32 *type, uint32 *len)
2953 /* right now that's enough ! */
2954 NT_PRINTER_PARAM *param;
2957 param=printer.info_2->specific;
2959 while (param != NULL && i < param_index) {
2967 /* exited because it exist */
2969 StrnCpy(value, param->value, sizeof(fstring)-1);
2970 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2973 ZERO_STRUCTP(*data);
2974 memcpy(*data, param->data, param->data_len);
2975 *len=param->data_len;
2979 /****************************************************************************
2980 ****************************************************************************/
2981 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2982 fstring value, uint8 **data, uint32 *type, uint32 *len)
2984 /* right now that's enough ! */
2985 NT_PRINTER_PARAM *param;
2987 DEBUG(10, ("get_specific_param\n"));
2989 param=printer.info_2->specific;
2991 while (param != NULL)
2993 #if 1 /* JRA - I think this should be case insensitive.... */
2994 if ( strequal(value, param->value)
2996 if ( !strcmp(value, param->value)
2998 && strlen(value)==strlen(param->value))
3006 DEBUGADD(10, ("get_specific_param: found one param\n"));
3007 /* exited because it exist */
3010 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3013 memcpy(*data, param->data, param->data_len);
3014 *len=param->data_len;
3016 DEBUGADD(10, ("get_specific_param: exit true\n"));
3019 DEBUGADD(10, ("get_specific_param: exit false\n"));
3023 /****************************************************************************
3024 Store a security desc for a printer.
3025 ****************************************************************************/
3027 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3029 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3030 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3032 TALLOC_CTX *mem_ctx = NULL;
3036 mem_ctx = talloc_init();
3037 if (mem_ctx == NULL)
3040 /* The old owner and group sids of the security descriptor are not
3041 present when new ACEs are added or removed by changing printer
3042 permissions through NT. If they are NULL in the new security
3043 descriptor then copy them over from the old one. */
3045 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3046 DOM_SID *owner_sid, *group_sid;
3047 SEC_ACL *dacl, *sacl;
3048 SEC_DESC *psd = NULL;
3051 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3053 /* Pick out correct owner and group sids */
3055 owner_sid = secdesc_ctr->sec->owner_sid ?
3056 secdesc_ctr->sec->owner_sid :
3057 old_secdesc_ctr->sec->owner_sid;
3059 group_sid = secdesc_ctr->sec->grp_sid ?
3060 secdesc_ctr->sec->grp_sid :
3061 old_secdesc_ctr->sec->grp_sid;
3063 dacl = secdesc_ctr->sec->dacl ?
3064 secdesc_ctr->sec->dacl :
3065 old_secdesc_ctr->sec->dacl;
3067 sacl = secdesc_ctr->sec->sacl ?
3068 secdesc_ctr->sec->sacl :
3069 old_secdesc_ctr->sec->sacl;
3071 /* Make a deep copy of the security descriptor */
3073 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3074 owner_sid, group_sid,
3079 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3082 if (!new_secdesc_ctr) {
3083 new_secdesc_ctr = secdesc_ctr;
3086 /* Store the security descriptor in a tdb */
3088 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3089 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3091 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3093 status = ERROR_INVALID_FUNCTION;
3097 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3099 if (tdb_prs_store(tdb, key, &ps)==0) {
3102 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3103 status = ERROR_INVALID_FUNCTION;
3106 /* Free malloc'ed memory */
3112 talloc_destroy(mem_ctx);
3116 /****************************************************************************
3117 Construct a default security descriptor buffer for a printer.
3118 ****************************************************************************/
3120 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3124 SEC_ACL *psa = NULL;
3125 SEC_DESC_BUF *sdb = NULL;
3126 SEC_DESC *psd = NULL;
3129 enum SID_NAME_USE name_type;
3131 /* Create an ACE where Everyone is allowed to print */
3133 init_sec_access(&sa, PRINTER_ACE_PRINT);
3134 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3135 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3137 /* Make the security descriptor owned by the Administrators group
3138 on the PDC of the domain. */
3140 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3141 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3145 /* Backup plan - make printer owned by admins or root.
3146 This should emulate a lanman printer as security
3147 settings can't be changed. */
3149 sid_peek_rid(&owner_sid, &owner_rid);
3151 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3152 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3153 owner_rid != DOMAIN_USER_RID_ADMIN &&
3154 !lookup_name("root", &owner_sid, &name_type)) {
3155 sid_copy(&owner_sid, &global_sid_World);
3159 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3160 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3161 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3162 SEC_ACE_FLAG_INHERIT_ONLY);
3164 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3165 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3166 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3168 /* The ACL revision number in rpc_secdesc.h differs from the one
3169 created by NT when setting ACE entries in printer
3170 descriptors. NT4 complains about the property being edited by a
3173 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3174 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3176 NULL, psa, &sd_size);
3180 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3184 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3186 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3187 (unsigned int)sd_size));
3192 /****************************************************************************
3193 Get a security desc for a printer.
3194 ****************************************************************************/
3196 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3202 if ((temp = strchr(printername + 2, '\\'))) {
3203 printername = temp + 1;
3206 /* Fetch security descriptor from tdb */
3208 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3210 if (tdb_prs_fetch(tdb, key, &ps, ctx)!=0 ||
3211 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3213 DEBUG(4,("using default secdesc for %s\n", printername));
3215 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3222 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3223 this security descriptor has been created when winbindd was
3224 down. Take ownership of security descriptor. */
3226 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3228 enum SID_NAME_USE name_type;
3230 /* Change sd owner to workgroup administrator */
3232 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3234 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3235 SEC_DESC *psd = NULL;
3240 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3242 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3244 (*secdesc_ctr)->sec->grp_sid,
3245 (*secdesc_ctr)->sec->sacl,
3246 (*secdesc_ctr)->sec->dacl,
3249 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3251 /* Swap with other one */
3253 *secdesc_ctr = new_secdesc_ctr;
3257 nt_printing_setsec(printername, *secdesc_ctr);
3261 if (DEBUGLEVEL >= 10) {
3262 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3265 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3266 printername, the_acl->num_aces));
3268 for (i = 0; i < the_acl->num_aces; i++) {
3271 sid_to_string(sid_str, &the_acl->ace[i].sid);
3273 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3274 the_acl->ace[i].type, the_acl->ace[i].flags,
3275 the_acl->ace[i].info.mask));
3285 1: level not implemented
3286 2: file doesn't exist
3287 3: can't allocate memory
3288 4: can't free memory
3289 5: non existant struct
3293 A printer and a printer driver are 2 different things.
3294 NT manages them separatelly, Samba does the same.
3295 Why ? Simply because it's easier and it makes sense !
3297 Now explanation: You have 3 printers behind your samba server,
3298 2 of them are the same make and model (laser A and B). But laser B
3299 has an 3000 sheet feeder and laser A doesn't such an option.
3300 Your third printer is an old dot-matrix model for the accounting :-).
3302 If the /usr/local/samba/lib directory (default dir), you will have
3303 5 files to describe all of this.
3305 3 files for the printers (1 by printer):
3308 NTprinter_accounting
3309 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3310 NTdriver_printer model X
3311 NTdriver_printer model Y
3313 jfm: I should use this comment for the text file to explain
3314 same thing for the forms BTW.
3315 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3319 /* Convert generic access rights to printer object specific access rights.
3320 It turns out that NT4 security descriptors use generic access rights and
3321 NT5 the object specific ones. */
3323 void map_printer_permissions(SEC_DESC *sd)
3327 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3328 se_map_generic(&sd->dacl->ace[i].info.mask,
3329 &printer_generic_mapping);
3333 /****************************************************************************
3334 Check a user has permissions to perform the given operation. We use the
3335 permission constants defined in include/rpc_spoolss.h to check the various
3336 actions we perform when checking printer access.
3338 PRINTER_ACCESS_ADMINISTER:
3339 print_queue_pause, print_queue_resume, update_printer_sec,
3340 update_printer, spoolss_addprinterex_level_2,
3341 _spoolss_setprinterdata
3346 JOB_ACCESS_ADMINISTER:
3347 print_job_delete, print_job_pause, print_job_resume,
3350 ****************************************************************************/
3351 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3353 SEC_DESC_BUF *secdesc = NULL;
3354 uint32 access_granted, status;
3357 TALLOC_CTX *mem_ctx = NULL;
3358 extern struct current_user current_user;
3360 /* If user is NULL then use the current_user structure */
3362 if (!user) user = ¤t_user;
3364 /* Always allow root or printer admins to do anything */
3366 if (user->uid == 0 ||
3367 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3371 /* Get printer name */
3373 pname = PRINTERNAME(snum);
3375 if (!pname || !*pname) {
3380 /* Get printer security descriptor */
3382 if(!(mem_ctx = talloc_init())) {
3387 nt_printing_getsec(mem_ctx, pname, &secdesc);
3389 if (access_type == JOB_ACCESS_ADMINISTER) {
3390 SEC_DESC_BUF *parent_secdesc = secdesc;
3392 /* Create a child security descriptor to check permissions
3393 against. This is because print jobs are child objects
3394 objects of a printer. */
3396 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3398 /* Now this is the bit that really confuses me. The access
3399 type needs to be changed from JOB_ACCESS_ADMINISTER to
3400 PRINTER_ACCESS_ADMINISTER for this to work. Something
3401 to do with the child (job) object becoming like a
3404 access_type = PRINTER_ACCESS_ADMINISTER;
3409 map_printer_permissions(secdesc->sec);
3411 result = se_access_check(secdesc->sec, user, access_type,
3412 &access_granted, &status);
3414 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3416 talloc_destroy(mem_ctx);
3424 /****************************************************************************
3425 Check the time parameters allow a print operation.
3426 *****************************************************************************/
3428 BOOL print_time_access_check(int snum)
3430 NT_PRINTER_INFO_LEVEL *printer = NULL;
3432 time_t now = time(NULL);
3436 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3439 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3443 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3445 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3448 free_a_printer(&printer, 2);
3456 /****************************************************************************
3457 Attempt to write a default device.
3458 *****************************************************************************/
3460 uint32 printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3462 NT_PRINTER_INFO_LEVEL *printer = NULL;
3467 * Don't bother if no default devicemode was sent.
3470 if (printer_default->devmode_cont.devmode == NULL)
3473 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3474 return ERROR_ACCESS_DENIED;
3477 * Just ignore it if we already have a devmode.
3480 if (printer->info_2->devmode != NULL)
3484 * We don't have a devicemode and we're trying to write
3485 * one. Check we have the access needed.
3487 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3489 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3490 PRINTER_ACCESS_ADMINISTER) {
3491 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3492 result = ERROR_ACCESS_DENIED;
3496 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3497 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3498 lp_servicename(snum) ));
3499 result = ERROR_ACCESS_DENIED;
3500 /*result = NT_STATUS_NO_PROBLEMO;*/
3504 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3507 * Convert the on the wire devicemode format to the internal one.
3510 if (!convert_devicemode(printer->info_2->printername,
3511 printer_default->devmode_cont.devmode,
3512 &printer->info_2->devmode)) {
3513 result = ERROR_NOT_ENOUGH_MEMORY;
3518 * Finally write back to the tdb.
3521 if (add_a_printer(*printer, 2)!=0) {
3522 result = ERROR_ACCESS_DENIED;
3528 free_a_printer(&printer, 2);