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_log(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 close_file(fsp, True);
648 close_cnum(conn, user->vuid);
655 close_file(fsp, True);
657 close_cnum(conn, user->vuid);
662 /****************************************************************************
663 ****************************************************************************/
664 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
665 struct current_user *user)
667 fstring architecture;
673 /* clean up the driver name.
674 * we can get .\driver.dll
675 * or worse c:\windows\system\driver.dll !
677 /* using an intermediate string to not have overlaping memcpy()'s */
678 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
679 fstrcpy(new_name, p+1);
680 fstrcpy(driver->driverpath, new_name);
683 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
684 fstrcpy(new_name, p+1);
685 fstrcpy(driver->datafile, new_name);
688 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
689 fstrcpy(new_name, p+1);
690 fstrcpy(driver->configfile, new_name);
693 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
694 fstrcpy(new_name, p+1);
695 fstrcpy(driver->helpfile, new_name);
698 if (driver->dependentfiles) {
699 for (i=0; *driver->dependentfiles[i]; i++) {
700 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
701 fstrcpy(new_name, p+1);
702 fstrcpy(driver->dependentfiles[i], new_name);
707 get_short_archi(architecture, driver->environment);
709 /* jfm:7/16/2000 the client always sends the cversion=0.
710 * The server should check which version the driver is by reading
711 * the PE header of driver->driverpath.
713 * For Windows 95/98 the version is 0 (so the value sent is correct)
714 * For Windows NT (the architecture doesn't matter)
716 * NT 3.5/3.51: cversion=1
720 if ((driver->cversion = get_correct_cversion( architecture,
721 driver->driverpath, user, &err)) == -1)
724 return NT_STATUS_NO_PROBLEMO;
727 /****************************************************************************
728 ****************************************************************************/
729 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
730 struct current_user *user)
732 fstring architecture;
738 /* clean up the driver name.
739 * we can get .\driver.dll
740 * or worse c:\windows\system\driver.dll !
742 /* using an intermediate string to not have overlaping memcpy()'s */
743 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
744 fstrcpy(new_name, p+1);
745 fstrcpy(driver->driverpath, new_name);
748 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
749 fstrcpy(new_name, p+1);
750 fstrcpy(driver->datafile, new_name);
753 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
754 fstrcpy(new_name, p+1);
755 fstrcpy(driver->configfile, new_name);
758 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
759 fstrcpy(new_name, p+1);
760 fstrcpy(driver->helpfile, new_name);
763 if (driver->dependentfiles) {
764 for (i=0; *driver->dependentfiles[i]; i++) {
765 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
766 fstrcpy(new_name, p+1);
767 fstrcpy(driver->dependentfiles[i], new_name);
772 get_short_archi(architecture, driver->environment);
774 /* jfm:7/16/2000 the client always sends the cversion=0.
775 * The server should check which version the driver is by reading
776 * the PE header of driver->driverpath.
778 * For Windows 95/98 the version is 0 (so the value sent is correct)
779 * For Windows NT (the architecture doesn't matter)
781 * NT 3.5/3.51: cversion=1
785 if ((driver->version = get_correct_cversion(architecture,
786 driver->driverpath, user, &err)) == -1)
789 return NT_STATUS_NO_PROBLEMO;
792 /****************************************************************************
793 ****************************************************************************/
794 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
795 uint32 level, struct current_user *user)
800 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
801 driver=driver_abstract.info_3;
802 return clean_up_driver_struct_level_3(driver, user);
806 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
807 driver=driver_abstract.info_6;
808 return clean_up_driver_struct_level_6(driver, user);
811 return ERROR_INVALID_PARAMETER;
815 /****************************************************************************
816 This function sucks and should be replaced. JRA.
817 ****************************************************************************/
819 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
821 dst->cversion = src->version;
823 fstrcpy( dst->name, src->name);
824 fstrcpy( dst->environment, src->environment);
825 fstrcpy( dst->driverpath, src->driverpath);
826 fstrcpy( dst->datafile, src->datafile);
827 fstrcpy( dst->configfile, src->configfile);
828 fstrcpy( dst->helpfile, src->helpfile);
829 fstrcpy( dst->monitorname, src->monitorname);
830 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
831 dst->dependentfiles = src->dependentfiles;
834 #if 0 /* Debugging function */
836 static char* ffmt(unsigned char *c){
838 static char ffmt_str[17];
840 for (i=0; i<16; i++) {
841 if ((c[i] < ' ') || (c[i] > '~'))
852 /****************************************************************************
853 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
854 There are two case to be covered here: PE (Portable Executable) and NE (New
855 Executable) files. Both files support the same INFO structure, but PE files
856 store the signature in unicode, and NE files store it as !unicode.
857 ****************************************************************************/
858 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
865 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
866 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
867 fname, PE_HEADER_SIZE));
871 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
872 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
873 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
875 goto no_version_info;
878 /* Is this really a DOS header? */
879 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
880 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
881 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
882 goto no_version_info;
885 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
886 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
887 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
889 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
890 goto no_version_info;
893 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
894 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
896 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
897 goto no_version_info;
900 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
901 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
903 int section_table_bytes;
905 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
906 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
907 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
908 /* At this point, we assume the file is in error. It still could be somthing
909 * else besides a PE file, but it unlikely at this point.
914 /* get the section table */
915 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
916 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
918 if ((buf=malloc(section_table_bytes)) == NULL) {
919 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
920 fname, section_table_bytes));
924 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
925 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
930 /* Iterate the section table looking for the resource section ".rsrc" */
931 for (i = 0; i < num_sections; i++) {
932 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
934 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
935 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
936 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
939 if ((buf=malloc(section_bytes)) == NULL) {
940 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
941 fname, section_bytes));
945 /* Seek to the start of the .rsrc section info */
946 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
947 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
952 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
953 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
958 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
959 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
960 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
961 /* Align to next long address */
962 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
964 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
965 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
966 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
968 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
969 fname, *major, *minor,
970 (*major>>16)&0xffff, *major&0xffff,
971 (*minor>>16)&0xffff, *minor&0xffff));
980 /* Version info not found, fall back to origin date/time */
981 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
985 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
986 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
987 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
988 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
989 /* At this point, we assume the file is in error. It still could be somthing
990 * else besides a NE file, but it unlikely at this point. */
994 /* Allocate a bit more space to speed up things */
996 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
997 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
998 fname, PE_HEADER_SIZE));
1002 /* This is a HACK! I got tired of trying to sort through the messy
1003 * 'NE' file format. If anyone wants to clean this up please have at
1004 * it, but this works. 'NE' files will eventually fade away. JRR */
1005 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1006 /* Cover case that should not occur in a well formed 'NE' .dll file */
1007 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1009 for(i=0; i<byte_count; i++) {
1010 /* Fast skip past data that can't possibly match */
1011 if (buf[i] != 'V') continue;
1013 /* Potential match data crosses buf boundry, move it to beginning
1014 * of buf, and fill the buf with as much as it will hold. */
1015 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1018 memcpy(buf, &buf[i], byte_count-i);
1019 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1020 (byte_count-i))) < 0) {
1022 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1027 byte_count = bc + (byte_count - i);
1028 if (byte_count<VS_VERSION_INFO_SIZE) break;
1033 /* Check that the full signature string and the magic number that
1034 * follows exist (not a perfect solution, but the chances that this
1035 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1036 * twice, as it is simpler to read the code. */
1037 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1038 /* Compute skip alignment to next long address */
1039 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1040 sizeof(VS_SIGNATURE)) & 3;
1041 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1043 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1044 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1045 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1046 fname, *major, *minor,
1047 (*major>>16)&0xffff, *major&0xffff,
1048 (*minor>>16)&0xffff, *minor&0xffff));
1055 /* Version info not found, fall back to origin date/time */
1056 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1061 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1062 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1063 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1074 /****************************************************************************
1075 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1076 share one or more files. During the MS installation process files are checked
1077 to insure that only a newer version of a shared file is installed over an
1078 older version. There are several possibilities for this comparison. If there
1079 is no previous version, the new one is newer (obviously). If either file is
1080 missing the version info structure, compare the creation date (on Unix use
1081 the modification date). Otherwise chose the numerically larger version number.
1082 ****************************************************************************/
1083 static int file_version_is_newer(connection_struct *conn, fstring new_file,
1086 BOOL use_version = True;
1091 time_t new_create_time;
1095 time_t old_create_time;
1099 files_struct *fsp = NULL;
1101 SMB_STRUCT_STAT stat_buf;
1105 ZERO_STRUCT(stat_buf);
1106 new_create_time = (time_t)0;
1107 old_create_time = (time_t)0;
1109 /* Get file version info (if available) for previous file (if it exists) */
1110 pstrcpy(filepath, old_file);
1112 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1114 fsp = open_file_shared(conn, filepath, &stat_buf,
1115 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1116 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1117 0, 0, &access_mode, &action);
1119 /* Old file not found, so by definition new file is in fact newer */
1120 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1125 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1126 if (ret == -1) goto error_exit;
1129 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1131 use_version = False;
1132 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1133 old_create_time = st.st_mtime;
1134 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1137 close_file(fsp, True);
1139 /* Get file version info (if available) for new file */
1140 pstrcpy(filepath, new_file);
1141 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1143 fsp = open_file_shared(conn, filepath, &stat_buf,
1144 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1145 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1146 0, 0, &access_mode, &action);
1148 /* New file not found, this shouldn't occur if the caller did its job */
1149 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1154 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1155 if (ret == -1) goto error_exit;
1158 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1160 use_version = False;
1161 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1162 new_create_time = st.st_mtime;
1163 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1166 close_file(fsp, True);
1169 /* Compare versions and choose the larger version number */
1170 if (new_major > old_major ||
1171 (new_major == old_major && new_minor > old_minor)) {
1173 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1177 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1182 /* Compare modification time/dates and choose the newest time/date */
1183 if (new_create_time > old_create_time) {
1184 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1188 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1195 close_file(fsp, True);
1199 /****************************************************************************
1200 ****************************************************************************/
1201 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1203 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1204 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1205 fstring architecture;
1211 connection_struct *conn;
1214 struct passwd *pass;
1220 memset(inbuf, '\0', sizeof(inbuf));
1221 memset(outbuf, '\0', sizeof(outbuf));
1224 driver=driver_abstract.info_3;
1225 else if (level==6) {
1226 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1227 driver = &converted_driver;
1229 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1233 get_short_archi(architecture, driver->environment);
1236 pass = sys_getpwuid(user->uid);
1238 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1239 (unsigned int)user->uid ));
1245 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1246 fstrcpy(user_name, pass->pw_name );
1247 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1249 /* Null password is ok - we are already an authenticated user... */
1251 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1254 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1255 *perr = (uint32)ecode;
1260 * Save who we are - we are temporarily becoming the connection user.
1265 if (!become_user(conn, conn->vuid)) {
1266 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1272 * make the directories version and version\driver_name
1273 * under the architecture directory.
1275 DEBUG(5,("Creating first directory\n"));
1276 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1277 mkdir_internal(conn, inbuf, outbuf, new_dir);
1279 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1280 * listed for this driver which has already been moved, skip it (note:
1281 * drivers may list the same file name several times. Then check if the
1282 * file already exists in archi\cversion\, if so, check that the version
1283 * info (or time stamps if version info is unavailable) is newer (or the
1284 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1285 * Otherwise, delete the file.
1287 * If a file is not moved to archi\cversion\ because of an error, all the
1288 * rest of the 'unmoved' driver files are removed from archi\. If one or
1289 * more of the driver's files was already moved to archi\cversion\, it
1290 * potentially leaves the driver in a partially updated state. Version
1291 * trauma will most likely occur if an client attempts to use any printer
1292 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1293 * done is appropriate... later JRR
1296 DEBUG(5,("Moving files now !\n"));
1298 if (driver->driverpath && strlen(driver->driverpath)) {
1299 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1300 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1301 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1302 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1303 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1304 new_name, old_name));
1305 *perr = (uint32)SVAL(outbuf,smb_err);
1306 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1311 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1314 if (driver->datafile && strlen(driver->datafile)) {
1315 if (!strequal(driver->datafile, driver->driverpath)) {
1316 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1317 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1318 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1319 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1320 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1321 new_name, old_name));
1322 *perr = (uint32)SVAL(outbuf,smb_err);
1323 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1328 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1332 if (driver->configfile && strlen(driver->configfile)) {
1333 if (!strequal(driver->configfile, driver->driverpath) &&
1334 !strequal(driver->configfile, driver->datafile)) {
1335 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1336 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1337 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1338 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1339 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1340 new_name, old_name));
1341 *perr = (uint32)SVAL(outbuf,smb_err);
1342 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1347 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1351 if (driver->helpfile && strlen(driver->helpfile)) {
1352 if (!strequal(driver->helpfile, driver->driverpath) &&
1353 !strequal(driver->helpfile, driver->datafile) &&
1354 !strequal(driver->helpfile, driver->configfile)) {
1355 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1356 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1357 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1358 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1359 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1360 new_name, old_name));
1361 *perr = (uint32)SVAL(outbuf,smb_err);
1362 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1367 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1371 if (driver->dependentfiles) {
1372 for (i=0; *driver->dependentfiles[i]; i++) {
1373 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1374 !strequal(driver->dependentfiles[i], driver->datafile) &&
1375 !strequal(driver->dependentfiles[i], driver->configfile) &&
1376 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1378 for (j=0; j < i; j++) {
1379 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1384 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1385 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1386 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1387 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1388 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1389 new_name, old_name));
1390 *perr = (uint32)SVAL(outbuf,smb_err);
1391 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1396 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1402 close_cnum(conn, user->vuid);
1405 return ver == -1 ? False : True;
1408 /****************************************************************************
1409 ****************************************************************************/
1410 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1413 fstring architecture;
1419 TDB_DATA kbuf, dbuf;
1421 get_short_archi(architecture, driver->environment);
1423 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1424 * \\server is added in the rpc server layer.
1425 * It does make sense to NOT store the server's name in the printer TDB.
1428 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1430 /* .inf files do not always list a file for each of the four standard files.
1431 * Don't prepend a path to a null filename, or client claims:
1432 * "The server on which the printer resides does not have a suitable
1433 * <printer driver name> printer driver installed. Click OK if you
1434 * wish to install the driver on your local machine."
1436 if (strlen(driver->driverpath)) {
1437 fstrcpy(temp_name, driver->driverpath);
1438 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1441 if (strlen(driver->datafile)) {
1442 fstrcpy(temp_name, driver->datafile);
1443 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1446 if (strlen(driver->configfile)) {
1447 fstrcpy(temp_name, driver->configfile);
1448 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1451 if (strlen(driver->helpfile)) {
1452 fstrcpy(temp_name, driver->helpfile);
1453 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1456 if (driver->dependentfiles) {
1457 for (i=0; *driver->dependentfiles[i]; i++) {
1458 fstrcpy(temp_name, driver->dependentfiles[i]);
1459 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1463 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1464 dos_to_unix(key, True); /* Convert key to unix-codepage */
1466 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1473 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1476 driver->environment,
1481 driver->monitorname,
1482 driver->defaultdatatype);
1484 if (driver->dependentfiles) {
1485 for (i=0; *driver->dependentfiles[i]; i++) {
1486 len += tdb_pack(buf+len, buflen-len, "f",
1487 driver->dependentfiles[i]);
1491 if (len != buflen) {
1492 buf = (char *)Realloc(buf, len);
1499 kbuf.dsize = strlen(key)+1;
1503 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1506 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1512 /****************************************************************************
1513 ****************************************************************************/
1514 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1516 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1519 info3.cversion = driver->version;
1520 fstrcpy(info3.name,driver->name);
1521 fstrcpy(info3.environment,driver->environment);
1522 fstrcpy(info3.driverpath,driver->driverpath);
1523 fstrcpy(info3.datafile,driver->datafile);
1524 fstrcpy(info3.configfile,driver->configfile);
1525 fstrcpy(info3.helpfile,driver->helpfile);
1526 fstrcpy(info3.monitorname,driver->monitorname);
1527 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1528 info3.dependentfiles = driver->dependentfiles;
1530 return add_a_printer_driver_3(&info3);
1534 /****************************************************************************
1535 ****************************************************************************/
1536 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1538 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1542 fstrcpy(info.name, in_prt);
1543 fstrcpy(info.defaultdatatype, "RAW");
1545 fstrcpy(info.driverpath, "");
1546 fstrcpy(info.datafile, "");
1547 fstrcpy(info.configfile, "");
1548 fstrcpy(info.helpfile, "");
1550 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1551 return ERROR_NOT_ENOUGH_MEMORY;
1553 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1554 fstrcpy(info.dependentfiles[0], "");
1556 *info_ptr = memdup(&info, sizeof(info));
1561 /****************************************************************************
1562 ****************************************************************************/
1563 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1565 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1566 TDB_DATA kbuf, dbuf;
1567 fstring architecture;
1572 ZERO_STRUCT(driver);
1574 get_short_archi(architecture, in_arch);
1576 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1578 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1581 kbuf.dsize = strlen(key)+1;
1583 dbuf = tdb_fetch(tdb, kbuf);
1585 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1587 if (!dbuf.dptr) return 5;
1589 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1598 driver.defaultdatatype);
1601 while (len < dbuf.dsize) {
1602 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1603 sizeof(fstring)*(i+2));
1604 if (driver.dependentfiles == NULL)
1607 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1608 &driver.dependentfiles[i]);
1611 if (driver.dependentfiles != NULL)
1612 fstrcpy(driver.dependentfiles[i], "");
1614 safe_free(dbuf.dptr);
1616 if (len != dbuf.dsize) {
1617 if (driver.dependentfiles != NULL)
1618 safe_free(driver.dependentfiles);
1620 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1623 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1628 /****************************************************************************
1629 ****************************************************************************/
1630 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1632 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1638 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1639 DEBUG(10,("driver key: [%s]\n", key));
1642 kbuf.dsize = strlen(key)+1;
1643 if (!tdb_exists(tdb, kbuf)) return False;
1646 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1648 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1649 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1650 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1651 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1652 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1653 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1654 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1656 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1657 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1658 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1660 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1661 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1662 pstrcat(line, info3->configfile);
1664 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1665 pstrcat(line, info3->datafile);
1667 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1668 pstrcat(line, info3->helpfile);
1670 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1671 pstrcat(line, info3->monitorname);
1673 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1676 for (i=0; info3->dependentfiles &&
1677 *info3->dependentfiles[i]; i++) {
1678 if (i) pstrcat(line, ","); /* don't end in a "," */
1679 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1680 pstrcat(line, info3->dependentfiles[i]);
1688 /****************************************************************************
1689 debugging function, dump at level 6 the struct in the logs
1690 ****************************************************************************/
1691 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1694 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1697 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1703 if (driver.info_3 == NULL)
1706 info3=driver.info_3;
1708 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1709 DEBUGADD(106,("name:[%s]\n", info3->name));
1710 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1711 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1712 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1713 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1714 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1715 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1716 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1718 for (i=0; info3->dependentfiles &&
1719 *info3->dependentfiles[i]; i++) {
1720 DEBUGADD(106,("dependentfile:[%s]\n",
1721 info3->dependentfiles[i]));
1728 DEBUGADD(1,("Level not implemented\n"));
1736 /****************************************************************************
1737 ****************************************************************************/
1738 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1742 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1744 if (!nt_devmode) return len;
1746 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1747 nt_devmode->devicename,
1748 nt_devmode->formname,
1750 nt_devmode->specversion,
1751 nt_devmode->driverversion,
1753 nt_devmode->driverextra,
1754 nt_devmode->orientation,
1755 nt_devmode->papersize,
1756 nt_devmode->paperlength,
1757 nt_devmode->paperwidth,
1760 nt_devmode->defaultsource,
1761 nt_devmode->printquality,
1764 nt_devmode->yresolution,
1765 nt_devmode->ttoption,
1766 nt_devmode->collate,
1767 nt_devmode->logpixels,
1770 nt_devmode->bitsperpel,
1771 nt_devmode->pelswidth,
1772 nt_devmode->pelsheight,
1773 nt_devmode->displayflags,
1774 nt_devmode->displayfrequency,
1775 nt_devmode->icmmethod,
1776 nt_devmode->icmintent,
1777 nt_devmode->mediatype,
1778 nt_devmode->dithertype,
1779 nt_devmode->reserved1,
1780 nt_devmode->reserved2,
1781 nt_devmode->panningwidth,
1782 nt_devmode->panningheight,
1783 nt_devmode->private);
1786 if (nt_devmode->private) {
1787 len += tdb_pack(buf+len, buflen-len, "B",
1788 nt_devmode->driverextra,
1789 nt_devmode->private);
1792 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1797 /****************************************************************************
1798 ****************************************************************************/
1799 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1803 while (param != NULL) {
1804 len += tdb_pack(buf+len, buflen-len, "pfdB",
1813 len += tdb_pack(buf+len, buflen-len, "p", param);
1819 /****************************************************************************
1820 delete a printer - this just deletes the printer info file, any open
1821 handles are not affected
1822 ****************************************************************************/
1823 uint32 del_a_printer(char *sharename)
1828 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1829 dos_to_unix(key, True); /* Convert key to unix-codepage */
1832 kbuf.dsize=strlen(key)+1;
1834 tdb_delete(tdb, kbuf);
1838 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1839 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1840 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1841 /****************************************************************************
1842 ****************************************************************************/
1843 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1847 int buflen, len, ret;
1848 TDB_DATA kbuf, dbuf;
1851 * in addprinter: no servername and the printer is the name
1852 * in setprinter: servername is \\server
1853 * and printer is \\server\\printer
1855 * Samba manages only local printers.
1856 * we currently don't support things like path=\\other_server\printer
1859 if (info->servername[0]!='\0') {
1860 trim_string(info->printername, info->servername, NULL);
1861 trim_string(info->printername, "\\", NULL);
1862 info->servername[0]='\0';
1866 * JFM: one day I'll forget.
1867 * below that's info->portname because that's the SAMBA sharename
1868 * and I made NT 'thinks' it's the portname
1869 * the info->sharename is the thing you can name when you add a printer
1870 * that's the short-name when you create shared printer for 95/98
1871 * So I've made a limitation in SAMBA: you can only have 1 printer model
1872 * behind a SAMBA share.
1880 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1883 info->default_priority,
1900 info->printprocessor,
1904 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1906 len += pack_specifics(info->specific, buf+len, buflen-len);
1908 if (buflen != len) {
1909 buf = (char *)Realloc(buf, len);
1915 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1916 dos_to_unix(key, True); /* Convert key to unix-codepage */
1919 kbuf.dsize = strlen(key)+1;
1923 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1926 DEBUG(8, ("error updating printer to tdb on disk\n"));
1930 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1931 info->sharename, info->drivername, info->portname, len));
1937 /****************************************************************************
1938 ****************************************************************************/
1939 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1941 NT_PRINTER_PARAM *current;
1943 DEBUG(108,("add_a_specific_param\n"));
1945 (*param)->next=NULL;
1947 if (info_2->specific == NULL)
1949 info_2->specific=*param;
1953 current=info_2->specific;
1954 while (current->next != NULL) {
1955 current=current->next;
1957 current->next=*param;
1963 /****************************************************************************
1964 ****************************************************************************/
1965 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1967 NT_PRINTER_PARAM *current;
1968 NT_PRINTER_PARAM *previous;
1970 current=info_2->specific;
1973 if (current==NULL) return (False);
1975 if ( !strcmp(current->value, param->value) &&
1976 (strlen(current->value)==strlen(param->value)) ) {
1977 DEBUG(109,("deleting first value\n"));
1978 info_2->specific=current->next;
1979 safe_free(current->data);
1981 DEBUG(109,("deleted first value\n"));
1985 current=previous->next;
1987 while ( current!=NULL ) {
1988 if (!strcmp(current->value, param->value) &&
1989 strlen(current->value)==strlen(param->value) ) {
1990 DEBUG(109,("deleting current value\n"));
1991 previous->next=current->next;
1992 safe_free(current->data);
1994 DEBUG(109,("deleted current value\n"));
1998 previous=previous->next;
1999 current=current->next;
2004 /****************************************************************************
2005 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2006 ****************************************************************************/
2007 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2009 NT_PRINTER_PARAM *param = *param_ptr;
2014 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2017 safe_free(param->data);
2023 /****************************************************************************
2024 Malloc and return an NT devicemode.
2025 ****************************************************************************/
2027 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2030 * should I init this ones ???
2031 nt_devmode->devicename
2035 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2037 if (nt_devmode == NULL) {
2038 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2042 ZERO_STRUCTP(nt_devmode);
2044 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2045 fstrcpy(nt_devmode->devicename, adevice);
2047 fstrcpy(nt_devmode->formname, "Letter");
2049 nt_devmode->specversion = 0x0401;
2050 nt_devmode->driverversion = 0x0400;
2051 nt_devmode->size = 0x00DC;
2052 nt_devmode->driverextra = 0x0000;
2053 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2054 DEFAULTSOURCE | COPIES | SCALE |
2055 PAPERSIZE | ORIENTATION;
2056 nt_devmode->orientation = 1;
2057 nt_devmode->papersize = PAPER_LETTER;
2058 nt_devmode->paperlength = 0;
2059 nt_devmode->paperwidth = 0;
2060 nt_devmode->scale = 0x64;
2061 nt_devmode->copies = 01;
2062 nt_devmode->defaultsource = BIN_FORMSOURCE;
2063 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2064 nt_devmode->color = COLOR_MONOCHROME;
2065 nt_devmode->duplex = DUP_SIMPLEX;
2066 nt_devmode->yresolution = 0;
2067 nt_devmode->ttoption = TT_SUBDEV;
2068 nt_devmode->collate = COLLATE_FALSE;
2069 nt_devmode->icmmethod = 0;
2070 nt_devmode->icmintent = 0;
2071 nt_devmode->mediatype = 0;
2072 nt_devmode->dithertype = 0;
2074 /* non utilisés par un driver d'imprimante */
2075 nt_devmode->logpixels = 0;
2076 nt_devmode->bitsperpel = 0;
2077 nt_devmode->pelswidth = 0;
2078 nt_devmode->pelsheight = 0;
2079 nt_devmode->displayflags = 0;
2080 nt_devmode->displayfrequency = 0;
2081 nt_devmode->reserved1 = 0;
2082 nt_devmode->reserved2 = 0;
2083 nt_devmode->panningwidth = 0;
2084 nt_devmode->panningheight = 0;
2086 nt_devmode->private = NULL;
2090 /****************************************************************************
2091 Deepcopy an NT devicemode.
2092 ****************************************************************************/
2094 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2096 NT_DEVICEMODE *new_nt_devicemode = NULL;
2098 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2099 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2103 new_nt_devicemode->private = NULL;
2104 if (nt_devicemode->private != NULL) {
2105 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2106 safe_free(new_nt_devicemode);
2107 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2112 return new_nt_devicemode;
2115 /****************************************************************************
2116 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2117 ****************************************************************************/
2119 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2121 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2123 if(nt_devmode == NULL)
2126 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2128 if(nt_devmode->private)
2129 safe_free(nt_devmode->private);
2131 safe_free(nt_devmode);
2132 *devmode_ptr = NULL;
2135 /****************************************************************************
2136 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2137 ****************************************************************************/
2138 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2140 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2141 NT_PRINTER_PARAM *param_ptr;
2146 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2148 free_nt_devicemode(&info->devmode);
2150 for(param_ptr = info->specific; param_ptr; ) {
2151 NT_PRINTER_PARAM *tofree = param_ptr;
2153 param_ptr = param_ptr->next;
2154 free_nt_printer_param(&tofree);
2157 safe_free(*info_ptr);
2162 /****************************************************************************
2163 ****************************************************************************/
2164 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2168 NT_DEVICEMODE devmode;
2170 ZERO_STRUCT(devmode);
2172 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2174 if (!*nt_devmode) return len;
2176 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2180 &devmode.specversion,
2181 &devmode.driverversion,
2183 &devmode.driverextra,
2184 &devmode.orientation,
2186 &devmode.paperlength,
2187 &devmode.paperwidth,
2190 &devmode.defaultsource,
2191 &devmode.printquality,
2194 &devmode.yresolution,
2200 &devmode.bitsperpel,
2202 &devmode.pelsheight,
2203 &devmode.displayflags,
2204 &devmode.displayfrequency,
2208 &devmode.dithertype,
2211 &devmode.panningwidth,
2212 &devmode.panningheight,
2215 if (devmode.private) {
2216 /* the len in tdb_unpack is an int value and
2217 * devmode.driverextra is only a short
2219 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2220 devmode.driverextra=(uint16)extra_len;
2222 /* check to catch an invalid TDB entry so we don't segfault */
2223 if (devmode.driverextra == 0) {
2224 devmode.private = NULL;
2228 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2230 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2231 if (devmode.private)
2232 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2237 /****************************************************************************
2238 ****************************************************************************/
2239 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2242 NT_PRINTER_PARAM param, *p;
2247 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2250 len += tdb_unpack(buf+len, buflen-len, "fdB",
2256 *list = memdup(¶m, sizeof(param));
2258 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2264 static void map_to_os2_driver(fstring drivername)
2266 static BOOL initialised=False;
2267 static fstring last_from,last_to;
2268 char *mapfile = lp_os2_driver_map();
2269 char **lines = NULL;
2273 if (!strlen(drivername))
2280 *last_from = *last_to = 0;
2284 if (strequal(drivername,last_from)) {
2285 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2286 fstrcpy(drivername,last_to);
2290 lines = file_lines_load(mapfile, &numlines, True);
2291 if (numlines == 0) {
2292 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2296 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2298 for( i = 0; i < numlines; i++) {
2299 char *nt_name = lines[i];
2300 char *os2_name = strchr(nt_name,'=');
2307 while (isspace(*nt_name))
2310 if (!*nt_name || strchr("#;",*nt_name))
2314 int l = strlen(nt_name);
2315 while (l && isspace(nt_name[l-1])) {
2321 while (isspace(*os2_name))
2325 int l = strlen(os2_name);
2326 while (l && isspace(os2_name[l-1])) {
2332 if (strequal(nt_name,drivername)) {
2333 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2334 fstrcpy(last_from,drivername);
2335 fstrcpy(last_to,os2_name);
2336 fstrcpy(drivername,os2_name);
2337 file_lines_free(lines);
2342 file_lines_free(lines);
2345 /****************************************************************************
2346 get a default printer info 2 struct
2347 ****************************************************************************/
2348 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2350 extern pstring global_myname;
2352 NT_PRINTER_INFO_LEVEL_2 info;
2356 snum = lp_servicenumber(sharename);
2358 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2359 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2360 global_myname, sharename);
2361 fstrcpy(info.sharename, sharename);
2362 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2363 fstrcpy(info.drivername, lp_printerdriver(snum));
2366 if (!*info.drivername)
2367 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2369 /* by setting the driver name to an empty string, a local NT admin
2370 can now run the **local** APW to install a local printer driver
2371 for a Samba shared printer in 2.2. Without this, drivers **must** be
2372 installed on the Samba server for NT clients --jerry */
2373 if (!*info.drivername)
2374 fstrcpy(info.drivername, "");
2378 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2380 pstrcpy(info.comment, "");
2381 fstrcpy(info.printprocessor, "winprint");
2382 fstrcpy(info.datatype, "RAW");
2384 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2385 | PRINTER_ATTRIBUTE_LOCAL \
2386 | PRINTER_ATTRIBUTE_RAW_ONLY \
2387 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2389 info.starttime = 0; /* Minutes since 12:00am GMT */
2390 info.untiltime = 0; /* Minutes since 12:00am GMT */
2392 info.default_priority = 1;
2393 info.setuptime = (uint32)time(NULL);
2395 #if 1 /* JRA - NO NOT CHANGE ! */
2396 info.devmode = NULL;
2399 * We should not return a default devicemode, as this causes
2400 * Win2K to not send the correct one on PCL drivers. It needs to
2401 * see a null devicemode so it can then overwrite the devicemode
2402 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2404 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2408 /* This will get the current RPC talloc context, but we should be
2409 passing this as a parameter... fixme... JRA ! */
2411 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2414 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2416 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2425 free_nt_devicemode(&info.devmode);
2429 /****************************************************************************
2430 ****************************************************************************/
2431 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2434 NT_PRINTER_INFO_LEVEL_2 info;
2436 TDB_DATA kbuf, dbuf;
2437 fstring printername;
2441 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2442 dos_to_unix(key, True); /* Convert key to unix-codepage */
2445 kbuf.dsize = strlen(key)+1;
2447 dbuf = tdb_fetch(tdb, kbuf);
2449 return get_a_printer_2_default(info_ptr, sharename);
2451 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2454 &info.default_priority,
2471 info.printprocessor,
2475 /* Samba has to have shared raw drivers. */
2476 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2478 /* Restore the stripped strings. */
2479 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2480 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2482 fstrcpy(info.printername, printername);
2484 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2485 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2487 /* This will get the current RPC talloc context, but we should be
2488 passing this as a parameter... fixme... JRA ! */
2490 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2492 /* Fix for OS/2 drivers. */
2494 if (get_remote_arch() == RA_OS2)
2495 map_to_os2_driver(info.drivername);
2497 safe_free(dbuf.dptr);
2498 *info_ptr=memdup(&info, sizeof(info));
2500 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2501 sharename, info.printername, info.drivername));
2507 /****************************************************************************
2508 debugging function, dump at level 6 the struct in the logs
2509 ****************************************************************************/
2510 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2513 NT_PRINTER_INFO_LEVEL_2 *info2;
2515 DEBUG(106,("Dumping printer at level [%d]\n", level));
2521 if (printer.info_2 == NULL)
2525 info2=printer.info_2;
2527 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2528 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2529 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2530 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2531 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2532 DEBUGADD(106,("status:[%d]\n", info2->status));
2533 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2534 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2535 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2536 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2537 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2539 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2540 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2541 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2542 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2543 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2544 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2545 DEBUGADD(106,("location:[%s]\n", info2->location));
2546 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2547 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2548 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2549 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2555 DEBUGADD(1,("Level not implemented\n"));
2563 /****************************************************************************
2564 Get the parameters we can substitute in an NT print job.
2565 ****************************************************************************/
2567 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2569 NT_PRINTER_INFO_LEVEL *printer = NULL;
2571 **printername = **sharename = **portname = '\0';
2573 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2576 fstrcpy(*printername, printer->info_2->printername);
2577 fstrcpy(*sharename, printer->info_2->sharename);
2578 fstrcpy(*portname, printer->info_2->portname);
2580 free_a_printer(&printer, 2);
2584 * The function below are the high level ones.
2585 * only those ones must be called from the spoolss code.
2589 /****************************************************************************
2590 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2591 ****************************************************************************/
2593 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2597 dump_a_printer(printer, level);
2603 printer.info_2->c_setprinter++;
2604 result=update_a_printer_2(printer.info_2);
2615 /****************************************************************************
2616 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2617 We split this out from mod_a_printer as it updates the id's and timestamps.
2618 ****************************************************************************/
2620 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2624 dump_a_printer(printer, level);
2631 * Update the changestamp.
2632 * Note we must *not* do this in mod_a_printer().
2635 time_t time_unix = time(NULL);
2636 unix_to_nt_time(&time_nt, time_unix);
2637 if (printer.info_2->changeid==time_nt.low)
2638 printer.info_2->changeid++;
2640 printer.info_2->changeid=time_nt.low;
2642 printer.info_2->c_setprinter++;
2644 result=update_a_printer_2(printer.info_2);
2655 /****************************************************************************
2656 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2657 ****************************************************************************/
2659 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2662 NT_PRINTER_INFO_LEVEL *printer = NULL;
2666 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2672 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2673 DEBUG(0,("get_a_printer: malloc fail.\n"));
2676 ZERO_STRUCTP(printer);
2677 result=get_a_printer_2(&printer->info_2, sharename);
2679 dump_a_printer(*printer, level);
2680 *pp_printer = printer;
2691 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2696 /****************************************************************************
2697 Deletes a NT_PRINTER_INFO_LEVEL struct.
2698 ****************************************************************************/
2700 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2703 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2705 DEBUG(104,("freeing a printer at level [%d]\n", level));
2707 if (printer == NULL)
2714 if (printer->info_2 != NULL)
2716 free_nt_printer_info_level_2(&printer->info_2);
2735 /****************************************************************************
2736 ****************************************************************************/
2737 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2740 DEBUG(104,("adding a printer at level [%d]\n", level));
2741 dump_a_printer_driver(driver, level);
2747 result=add_a_printer_driver_3(driver.info_3);
2753 result=add_a_printer_driver_6(driver.info_6);
2763 /****************************************************************************
2764 ****************************************************************************/
2765 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2766 fstring printername, fstring architecture, uint32 version)
2774 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2783 dump_a_printer_driver(*driver, level);
2787 /****************************************************************************
2788 ****************************************************************************/
2789 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2797 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2798 if (driver.info_3 != NULL)
2800 info3=driver.info_3;
2801 safe_free(info3->dependentfiles);
2802 ZERO_STRUCTP(info3);
2814 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2815 if (driver.info_6 != NULL)
2817 info6=driver.info_6;
2818 safe_free(info6->dependentfiles);
2819 safe_free(info6->previousnames);
2820 ZERO_STRUCTP(info6);
2838 /****************************************************************************
2839 Determine whether or not a particular driver is currently assigned
2841 ****************************************************************************/
2842 BOOL printer_driver_in_use (char *arch, char *driver)
2844 TDB_DATA kbuf, newkey, dbuf;
2845 NT_PRINTER_INFO_LEVEL_2 info;
2851 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
2853 /* loop through the printers.tdb and check for the drivername */
2854 for (kbuf = tdb_firstkey(tdb); kbuf.dptr;
2855 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
2858 dbuf = tdb_fetch(tdb, kbuf);
2862 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
2865 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
2868 &info.default_priority,
2885 info.printprocessor,
2889 safe_free(dbuf.dptr);
2892 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
2897 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
2898 info.printername, info.drivername));
2900 if (strcmp(info.drivername, driver) == 0)
2902 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
2903 info.printername, driver));
2907 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
2911 /* report that the driver is in use by default */
2915 /****************************************************************************
2916 Remove a printer driver from the TDB. This assumes that the the driver was
2917 previously looked up.
2918 ***************************************************************************/
2919 uint32 delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
2926 get_short_archi(arch, i->environment);
2927 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
2928 arch, i->cversion, i->name);
2929 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
2932 kbuf.dsize=strlen(key)+1;
2934 if (tdb_delete(tdb, kbuf) == -1) {
2935 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
2936 return NT_STATUS_ACCESS_VIOLATION;
2939 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
2942 return NT_STATUS_NO_PROBLEMO;
2944 /****************************************************************************
2945 ****************************************************************************/
2946 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2947 fstring value, uint8 **data, uint32 *type, uint32 *len)
2949 /* right now that's enough ! */
2950 NT_PRINTER_PARAM *param;
2953 param=printer.info_2->specific;
2955 while (param != NULL && i < param_index) {
2963 /* exited because it exist */
2965 StrnCpy(value, param->value, sizeof(fstring)-1);
2966 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2969 ZERO_STRUCTP(*data);
2970 memcpy(*data, param->data, param->data_len);
2971 *len=param->data_len;
2975 /****************************************************************************
2976 ****************************************************************************/
2977 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2978 fstring value, uint8 **data, uint32 *type, uint32 *len)
2980 /* right now that's enough ! */
2981 NT_PRINTER_PARAM *param;
2983 DEBUG(10, ("get_specific_param\n"));
2985 param=printer.info_2->specific;
2987 while (param != NULL)
2989 #if 1 /* JRA - I think this should be case insensitive.... */
2990 if ( strequal(value, param->value)
2992 if ( !strcmp(value, param->value)
2994 && strlen(value)==strlen(param->value))
3002 DEBUGADD(10, ("get_specific_param: found one param\n"));
3003 /* exited because it exist */
3006 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3009 memcpy(*data, param->data, param->data_len);
3010 *len=param->data_len;
3012 DEBUGADD(10, ("get_specific_param: exit true\n"));
3015 DEBUGADD(10, ("get_specific_param: exit false\n"));
3019 /****************************************************************************
3020 Store a security desc for a printer.
3021 ****************************************************************************/
3023 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3025 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3026 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3028 TALLOC_CTX *mem_ctx = NULL;
3032 mem_ctx = talloc_init();
3033 if (mem_ctx == NULL)
3036 /* The old owner and group sids of the security descriptor are not
3037 present when new ACEs are added or removed by changing printer
3038 permissions through NT. If they are NULL in the new security
3039 descriptor then copy them over from the old one. */
3041 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3042 DOM_SID *owner_sid, *group_sid;
3043 SEC_ACL *dacl, *sacl;
3044 SEC_DESC *psd = NULL;
3047 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3049 /* Pick out correct owner and group sids */
3051 owner_sid = secdesc_ctr->sec->owner_sid ?
3052 secdesc_ctr->sec->owner_sid :
3053 old_secdesc_ctr->sec->owner_sid;
3055 group_sid = secdesc_ctr->sec->grp_sid ?
3056 secdesc_ctr->sec->grp_sid :
3057 old_secdesc_ctr->sec->grp_sid;
3059 dacl = secdesc_ctr->sec->dacl ?
3060 secdesc_ctr->sec->dacl :
3061 old_secdesc_ctr->sec->dacl;
3063 sacl = secdesc_ctr->sec->sacl ?
3064 secdesc_ctr->sec->sacl :
3065 old_secdesc_ctr->sec->sacl;
3067 /* Make a deep copy of the security descriptor */
3069 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3070 owner_sid, group_sid,
3075 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3078 if (!new_secdesc_ctr) {
3079 new_secdesc_ctr = secdesc_ctr;
3082 /* Store the security descriptor in a tdb */
3084 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3085 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3087 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3089 status = ERROR_INVALID_FUNCTION;
3093 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3095 if (tdb_prs_store(tdb, key, &ps)==0) {
3098 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3099 status = ERROR_INVALID_FUNCTION;
3102 /* Free malloc'ed memory */
3108 talloc_destroy(mem_ctx);
3112 /****************************************************************************
3113 Construct a default security descriptor buffer for a printer.
3114 ****************************************************************************/
3116 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3120 SEC_ACL *psa = NULL;
3121 SEC_DESC_BUF *sdb = NULL;
3122 SEC_DESC *psd = NULL;
3125 enum SID_NAME_USE name_type;
3127 /* Create an ACE where Everyone is allowed to print */
3129 init_sec_access(&sa, PRINTER_ACE_PRINT);
3130 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3131 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3133 /* Make the security descriptor owned by the Administrators group
3134 on the PDC of the domain. */
3136 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3137 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3141 /* Backup plan - make printer owned by admins or root.
3142 This should emulate a lanman printer as security
3143 settings can't be changed. */
3145 sid_peek_rid(&owner_sid, &owner_rid);
3147 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3148 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3149 owner_rid != DOMAIN_USER_RID_ADMIN &&
3150 !lookup_name("root", &owner_sid, &name_type)) {
3151 sid_copy(&owner_sid, &global_sid_World);
3155 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3156 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3157 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3158 SEC_ACE_FLAG_INHERIT_ONLY);
3160 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3161 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3162 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3164 /* The ACL revision number in rpc_secdesc.h differs from the one
3165 created by NT when setting ACE entries in printer
3166 descriptors. NT4 complains about the property being edited by a
3169 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3170 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3172 NULL, psa, &sd_size);
3176 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3180 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3182 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3183 (unsigned int)sd_size));
3188 /****************************************************************************
3189 Get a security desc for a printer.
3190 ****************************************************************************/
3192 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3198 if ((temp = strchr(printername + 2, '\\'))) {
3199 printername = temp + 1;
3202 /* Fetch security descriptor from tdb */
3204 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3206 if (tdb_prs_fetch(tdb, key, &ps, ctx)!=0 ||
3207 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3209 DEBUG(4,("using default secdesc for %s\n", printername));
3211 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3218 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3219 this security descriptor has been created when winbindd was
3220 down. Take ownership of security descriptor. */
3222 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3224 enum SID_NAME_USE name_type;
3226 /* Change sd owner to workgroup administrator */
3228 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3230 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3231 SEC_DESC *psd = NULL;
3236 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3238 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3240 (*secdesc_ctr)->sec->grp_sid,
3241 (*secdesc_ctr)->sec->sacl,
3242 (*secdesc_ctr)->sec->dacl,
3245 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3247 /* Swap with other one */
3249 *secdesc_ctr = new_secdesc_ctr;
3253 nt_printing_setsec(printername, *secdesc_ctr);
3257 if (DEBUGLEVEL >= 10) {
3258 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3261 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3262 printername, the_acl->num_aces));
3264 for (i = 0; i < the_acl->num_aces; i++) {
3267 sid_to_string(sid_str, &the_acl->ace[i].sid);
3269 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3270 the_acl->ace[i].type, the_acl->ace[i].flags,
3271 the_acl->ace[i].info.mask));
3281 1: level not implemented
3282 2: file doesn't exist
3283 3: can't allocate memory
3284 4: can't free memory
3285 5: non existant struct
3289 A printer and a printer driver are 2 different things.
3290 NT manages them separatelly, Samba does the same.
3291 Why ? Simply because it's easier and it makes sense !
3293 Now explanation: You have 3 printers behind your samba server,
3294 2 of them are the same make and model (laser A and B). But laser B
3295 has an 3000 sheet feeder and laser A doesn't such an option.
3296 Your third printer is an old dot-matrix model for the accounting :-).
3298 If the /usr/local/samba/lib directory (default dir), you will have
3299 5 files to describe all of this.
3301 3 files for the printers (1 by printer):
3304 NTprinter_accounting
3305 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3306 NTdriver_printer model X
3307 NTdriver_printer model Y
3309 jfm: I should use this comment for the text file to explain
3310 same thing for the forms BTW.
3311 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3315 /* Convert generic access rights to printer object specific access rights.
3316 It turns out that NT4 security descriptors use generic access rights and
3317 NT5 the object specific ones. */
3319 void map_printer_permissions(SEC_DESC *sd)
3323 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3324 se_map_generic(&sd->dacl->ace[i].info.mask,
3325 &printer_generic_mapping);
3329 /****************************************************************************
3330 Check a user has permissions to perform the given operation. We use the
3331 permission constants defined in include/rpc_spoolss.h to check the various
3332 actions we perform when checking printer access.
3334 PRINTER_ACCESS_ADMINISTER:
3335 print_queue_pause, print_queue_resume, update_printer_sec,
3336 update_printer, spoolss_addprinterex_level_2,
3337 _spoolss_setprinterdata
3342 JOB_ACCESS_ADMINISTER:
3343 print_job_delete, print_job_pause, print_job_resume,
3346 ****************************************************************************/
3347 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3349 SEC_DESC_BUF *secdesc = NULL;
3350 uint32 access_granted, status;
3353 TALLOC_CTX *mem_ctx = NULL;
3354 extern struct current_user current_user;
3356 /* If user is NULL then use the current_user structure */
3358 if (!user) user = ¤t_user;
3360 /* Always allow root or printer admins to do anything */
3362 if (user->uid == 0 ||
3363 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3367 /* Get printer name */
3369 pname = PRINTERNAME(snum);
3371 if (!pname || !*pname) {
3376 /* Get printer security descriptor */
3378 if(!(mem_ctx = talloc_init())) {
3383 nt_printing_getsec(mem_ctx, pname, &secdesc);
3385 if (access_type == JOB_ACCESS_ADMINISTER) {
3386 SEC_DESC_BUF *parent_secdesc = secdesc;
3388 /* Create a child security descriptor to check permissions
3389 against. This is because print jobs are child objects
3390 objects of a printer. */
3392 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3394 /* Now this is the bit that really confuses me. The access
3395 type needs to be changed from JOB_ACCESS_ADMINISTER to
3396 PRINTER_ACCESS_ADMINISTER for this to work. Something
3397 to do with the child (job) object becoming like a
3400 access_type = PRINTER_ACCESS_ADMINISTER;
3405 map_printer_permissions(secdesc->sec);
3407 result = se_access_check(secdesc->sec, user, access_type,
3408 &access_granted, &status);
3410 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3412 talloc_destroy(mem_ctx);
3420 /****************************************************************************
3421 Check the time parameters allow a print operation.
3422 *****************************************************************************/
3424 BOOL print_time_access_check(int snum)
3426 NT_PRINTER_INFO_LEVEL *printer = NULL;
3428 time_t now = time(NULL);
3432 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3435 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3439 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3441 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3444 free_a_printer(&printer, 2);
3452 /****************************************************************************
3453 Attempt to write a default device.
3454 *****************************************************************************/
3456 uint32 printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3458 NT_PRINTER_INFO_LEVEL *printer = NULL;
3463 * Don't bother if no default devicemode was sent.
3466 if (printer_default->devmode_cont.devmode == NULL)
3469 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3470 return ERROR_ACCESS_DENIED;
3473 * Just ignore it if we already have a devmode.
3476 if (printer->info_2->devmode != NULL)
3480 * We don't have a devicemode and we're trying to write
3481 * one. Check we have the access needed.
3483 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3485 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3486 PRINTER_ACCESS_ADMINISTER) {
3487 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3488 result = ERROR_ACCESS_DENIED;
3492 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3493 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3494 lp_servicename(snum) ));
3495 result = ERROR_ACCESS_DENIED;
3496 /*result = NT_STATUS_NO_PROBLEMO;*/
3500 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3503 * Convert the on the wire devicemode format to the internal one.
3506 if (!convert_devicemode(printer->info_2->printername,
3507 printer_default->devmode_cont.devmode,
3508 &printer->info_2->devmode)) {
3509 result = ERROR_NOT_ENOUGH_MEMORY;
3514 * Finally write back to the tdb.
3517 if (add_a_printer(*printer, 2)!=0) {
3518 result = ERROR_ACCESS_DENIED;
3524 free_a_printer(&printer, 2);