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 DATABASE_VERSION 1
37 /* Map generic permissions to printer object specific permissions */
39 struct generic_mapping printer_generic_mapping = {
46 /* We need one default form to support our default printer. Msoft adds the
47 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
48 array index). Letter is always first, so (for the current code) additions
49 always put things in the correct order. */
50 static nt_forms_struct default_forms[] = {
51 {"Letter", 0x2, 0x34b5b, 0x44367, 0x0, 0x0, 0x34b5b, 0x44367},
53 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
54 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
55 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
56 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
57 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
58 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
59 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
60 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
61 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
62 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
63 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
64 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
65 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
66 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
67 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
68 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
69 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
70 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
71 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
72 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
73 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
74 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
75 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
76 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
77 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
78 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
79 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
80 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
81 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
82 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
83 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
84 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
85 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
86 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
87 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
88 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
89 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
90 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
91 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
92 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
93 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
94 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
95 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
96 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
97 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
98 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
99 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
100 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
101 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
102 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
103 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
104 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
105 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
106 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
107 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
108 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
109 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
110 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
111 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
112 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
113 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
114 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
115 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
116 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
117 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
118 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
119 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
120 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
121 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
122 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
123 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
124 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
125 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
126 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
127 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
128 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
129 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
130 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
131 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
132 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
133 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
134 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
135 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
136 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
137 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
138 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
139 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
140 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
141 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
142 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
143 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
144 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
145 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
146 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
147 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
148 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
149 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
150 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
151 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
152 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
153 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
154 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
155 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
156 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
157 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
158 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
159 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
160 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
161 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
162 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
163 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
164 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
165 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
166 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
167 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
168 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
169 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
170 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
174 /****************************************************************************
175 open the NT printing tdb
176 ****************************************************************************/
177 BOOL nt_printing_init(void)
179 static pid_t local_pid;
180 char *vstring = "INFO/version";
182 if (tdb && local_pid == sys_getpid()) return True;
183 tdb = tdb_open(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
185 DEBUG(0,("Failed to open nt drivers database\n"));
189 local_pid = sys_getpid();
191 /* handle a Samba upgrade */
192 tdb_lock_bystring(tdb, vstring);
193 if (tdb_fetch_int(tdb, vstring) != DATABASE_VERSION) {
194 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
195 tdb_store_int(tdb, vstring, DATABASE_VERSION);
197 tdb_unlock_bystring(tdb, vstring);
202 /****************************************************************************
203 get builtin form struct list
204 ****************************************************************************/
205 int get_builtin_ntforms(nt_forms_struct **list)
207 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
208 return sizeof(default_forms) / sizeof(default_forms[0]);
211 /****************************************************************************
212 get a builtin form struct
213 ****************************************************************************/
215 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
219 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
220 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
221 count = sizeof(default_forms) / sizeof(default_forms[0]);
222 for (i=0;i<count;i++) {
223 if (strequal(form_name,default_forms[i].name)) {
224 DEBUGADD(6,("Found builtin form %s \n", form_name));
225 memcpy(form,&default_forms[i],sizeof(*form));
233 /****************************************************************************
234 get a form struct list
235 ****************************************************************************/
236 int get_ntforms(nt_forms_struct **list)
238 TDB_DATA kbuf, newkey, dbuf;
239 nt_forms_struct form;
244 for (kbuf = tdb_firstkey(tdb);
246 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
247 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
249 dbuf = tdb_fetch(tdb, kbuf);
250 if (!dbuf.dptr) continue;
252 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
253 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
254 &i, &form.flag, &form.width, &form.length, &form.left,
255 &form.top, &form.right, &form.bottom);
256 safe_free(dbuf.dptr);
257 if (ret != dbuf.dsize) continue;
259 *list = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
261 DEBUG(0,("get_ntforms: Realloc fail.\n"));
272 /****************************************************************************
273 write a form struct list
274 ****************************************************************************/
275 int write_ntforms(nt_forms_struct **list, int number)
282 for (i=0;i<number;i++) {
283 /* save index, so list is rebuilt in correct order */
284 len = tdb_pack(buf, sizeof(buf), "dddddddd",
285 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
286 (*list)[i].left, (*list)[i].top, (*list)[i].right,
288 if (len > sizeof(buf)) break;
289 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[i].name);
290 dos_to_unix(key, True); /* Convert key to unix-codepage */
291 kbuf.dsize = strlen(key)+1;
295 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
301 /****************************************************************************
302 add a form struct at the end of the list
303 ****************************************************************************/
304 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
311 * NT tries to add forms even when
312 * they are already in the base
313 * only update the values if already present
318 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
319 for (n=0; n<*count; n++) {
320 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
321 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
328 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
330 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
334 (*list)[n].flag=form->flags;
335 (*list)[n].width=form->size_x;
336 (*list)[n].length=form->size_y;
337 (*list)[n].left=form->left;
338 (*list)[n].top=form->top;
339 (*list)[n].right=form->right;
340 (*list)[n].bottom=form->bottom;
345 /****************************************************************************
346 delete a named form struct
347 ****************************************************************************/
348 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
357 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
359 for (n=0; n<*count; n++) {
360 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
361 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
367 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
368 *ret = ERROR_INVALID_PARAMETER;
372 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
373 dos_to_unix(key, True); /* Convert key to unix-codepage */
374 kbuf.dsize = strlen(key)+1;
376 if (tdb_delete(tdb, kbuf) != 0) {
377 *ret = ERROR_NOT_ENOUGH_MEMORY;
384 /****************************************************************************
386 ****************************************************************************/
387 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
391 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
393 DEBUG(106, ("[%s]\n", form_name));
394 for (n=0; n<count; n++)
396 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
397 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
401 if (n==count) return;
403 (*list)[n].flag=form->flags;
404 (*list)[n].width=form->size_x;
405 (*list)[n].length=form->size_y;
406 (*list)[n].left=form->left;
407 (*list)[n].top=form->top;
408 (*list)[n].right=form->right;
409 (*list)[n].bottom=form->bottom;
412 /****************************************************************************
413 get the nt drivers list
415 traverse the database and look-up the matching names
416 ****************************************************************************/
417 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
422 TDB_DATA kbuf, newkey;
424 get_short_archi(short_archi, architecture);
425 slprintf(key, sizeof(key), "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
427 for (kbuf = tdb_firstkey(tdb);
429 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
430 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
432 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
435 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
442 /****************************************************************************
443 function to do the mapping between the long architecture name and
445 ****************************************************************************/
446 BOOL get_short_archi(char *short_archi, char *long_archi)
453 struct table archi_table[]=
455 {"Windows 4.0", "WIN40" },
456 {"Windows NT x86", "W32X86" },
457 {"Windows NT R4000", "W32MIPS" },
458 {"Windows NT Alpha_AXP", "W32ALPHA" },
459 {"Windows NT PowerPC", "W32PPC" },
465 DEBUG(107,("Getting architecture dependant directory\n"));
468 } while ( (archi_table[i].long_archi!=NULL ) &&
469 StrCaseCmp(long_archi, archi_table[i].long_archi) );
471 if (archi_table[i].long_archi==NULL) {
472 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
476 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
478 DEBUGADD(108,("index: [%d]\n", i));
479 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
480 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
485 /****************************************************************************
486 Determine the correct cVersion associated with an architecture and driver
487 ****************************************************************************/
488 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
489 struct current_user *user, uint32 *perr)
495 char buf[PE_HEADER_SIZE];
500 files_struct *fsp = NULL;
504 connection_struct *conn;
508 /* If architecture is Windows 95/98, the version is always 0. */
509 if (strcmp(architecture, "WIN40") == 0) {
510 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
515 pass = sys_getpwuid(user->uid);
517 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
518 (unsigned int)user->uid ));
520 *perr = ERROR_ACCESS_DENIED;
525 /* connect to the print$ share under the same account as the user connected
527 fstrcpy(user_name, pass->pw_name );
528 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
530 /* Null password is ok - we are already an authenticated user... */
532 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
535 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
536 *perr = (uint32)ecode;
540 /* Save who we are - we are temporarily becoming the connection user. */
543 if (!become_user(conn, conn->vuid)) {
544 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
545 *perr = ERROR_ACCESS_DENIED;
550 /* Open the driver file (Portable Executable format) and determine the
551 * deriver the cversion. */
552 slprintf(driverpath, sizeof(driverpath), "%s/%s", architecture, driverpath_in);
554 unix_convert(driverpath,conn,NULL,&bad_path,&st);
556 fsp = open_file_shared(conn, driverpath, &st,
557 SET_OPEN_MODE(DOS_OPEN_RDONLY),
558 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
559 0, 0, &access_mode, &action);
561 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
563 *perr = ERROR_ACCESS_DENIED;
567 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
568 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
569 driverpath, byte_count));
570 *perr = NT_STATUS_FILE_INVALID;
574 /* Is this really a DOS header? */
575 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
576 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
577 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
578 *perr = NT_STATUS_FILE_INVALID;
582 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
583 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
584 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
586 *perr = NT_STATUS_FILE_INVALID;
590 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
591 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
592 driverpath, byte_count));
593 *perr = NT_STATUS_FILE_INVALID;
597 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
598 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
599 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
601 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
602 case 4: cversion = 2; break; /* Win NT 4 */
603 case 5: cversion = 3; break; /* Win 2000 */
605 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
606 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
607 *perr = NT_STATUS_FILE_INVALID;
611 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
612 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
613 *perr = NT_STATUS_FILE_INVALID;
617 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
618 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
620 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
621 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
622 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
624 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
625 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
626 *perr = NT_STATUS_FILE_INVALID;
630 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
631 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
632 *perr = NT_STATUS_FILE_INVALID;
637 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
638 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
639 *perr = NT_STATUS_FILE_INVALID;
643 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
644 driverpath, cversion));
646 fsp->conn->vfs_ops.close(fsp, fsp->fd);
648 close_cnum(conn, user->vuid);
656 fsp->conn->vfs_ops.close(fsp, fsp->fd);
660 close_cnum(conn, user->vuid);
665 /****************************************************************************
666 ****************************************************************************/
667 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
668 struct current_user *user)
670 fstring architecture;
676 /* clean up the driver name.
677 * we can get .\driver.dll
678 * or worse c:\windows\system\driver.dll !
680 /* using an intermediate string to not have overlaping memcpy()'s */
681 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
682 fstrcpy(new_name, p+1);
683 fstrcpy(driver->driverpath, new_name);
686 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
687 fstrcpy(new_name, p+1);
688 fstrcpy(driver->datafile, new_name);
691 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
692 fstrcpy(new_name, p+1);
693 fstrcpy(driver->configfile, new_name);
696 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
697 fstrcpy(new_name, p+1);
698 fstrcpy(driver->helpfile, new_name);
701 if (driver->dependentfiles) {
702 for (i=0; *driver->dependentfiles[i]; i++) {
703 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
704 fstrcpy(new_name, p+1);
705 fstrcpy(driver->dependentfiles[i], new_name);
710 get_short_archi(architecture, driver->environment);
712 /* jfm:7/16/2000 the client always sends the cversion=0.
713 * The server should check which version the driver is by reading
714 * the PE header of driver->driverpath.
716 * For Windows 95/98 the version is 0 (so the value sent is correct)
717 * For Windows NT (the architecture doesn't matter)
719 * NT 3.5/3.51: cversion=1
723 if ((driver->cversion = get_correct_cversion( architecture,
724 driver->driverpath, user, &err)) == -1)
727 return NT_STATUS_NO_PROBLEMO;
730 /****************************************************************************
731 ****************************************************************************/
732 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
733 struct current_user *user)
735 fstring architecture;
741 /* clean up the driver name.
742 * we can get .\driver.dll
743 * or worse c:\windows\system\driver.dll !
745 /* using an intermediate string to not have overlaping memcpy()'s */
746 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
747 fstrcpy(new_name, p+1);
748 fstrcpy(driver->driverpath, new_name);
751 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
752 fstrcpy(new_name, p+1);
753 fstrcpy(driver->datafile, new_name);
756 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
757 fstrcpy(new_name, p+1);
758 fstrcpy(driver->configfile, new_name);
761 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
762 fstrcpy(new_name, p+1);
763 fstrcpy(driver->helpfile, new_name);
766 if (driver->dependentfiles) {
767 for (i=0; *driver->dependentfiles[i]; i++) {
768 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
769 fstrcpy(new_name, p+1);
770 fstrcpy(driver->dependentfiles[i], new_name);
775 get_short_archi(architecture, driver->environment);
777 /* jfm:7/16/2000 the client always sends the cversion=0.
778 * The server should check which version the driver is by reading
779 * the PE header of driver->driverpath.
781 * For Windows 95/98 the version is 0 (so the value sent is correct)
782 * For Windows NT (the architecture doesn't matter)
784 * NT 3.5/3.51: cversion=1
788 if ((driver->version = get_correct_cversion(architecture,
789 driver->driverpath, user, &err)) == -1)
792 return NT_STATUS_NO_PROBLEMO;
795 /****************************************************************************
796 ****************************************************************************/
797 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
798 uint32 level, struct current_user *user)
803 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
804 driver=driver_abstract.info_3;
805 return clean_up_driver_struct_level_3(driver, user);
809 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
810 driver=driver_abstract.info_6;
811 return clean_up_driver_struct_level_6(driver, user);
814 return ERROR_INVALID_PARAMETER;
818 /****************************************************************************
819 This function sucks and should be replaced. JRA.
820 ****************************************************************************/
822 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
824 dst->cversion = src->version;
826 fstrcpy( dst->name, src->name);
827 fstrcpy( dst->environment, src->environment);
828 fstrcpy( dst->driverpath, src->driverpath);
829 fstrcpy( dst->datafile, src->datafile);
830 fstrcpy( dst->configfile, src->configfile);
831 fstrcpy( dst->helpfile, src->helpfile);
832 fstrcpy( dst->monitorname, src->monitorname);
833 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
834 dst->dependentfiles = src->dependentfiles;
837 #if 0 /* Debugging function */
839 static char* ffmt(unsigned char *c){
841 static char ffmt_str[17];
843 for (i=0; i<16; i++) {
844 if ((c[i] < ' ') || (c[i] > '~'))
855 /****************************************************************************
856 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
857 There are two case to be covered here: PE (Portable Executable) and NE (New
858 Executable) files. Both files support the same INFO structure, but PE files
859 store the signature in unicode, and NE files store it as !unicode.
860 ****************************************************************************/
861 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
868 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
869 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
870 fname, PE_HEADER_SIZE));
874 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
875 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
876 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
878 goto no_version_info;
881 /* Is this really a DOS header? */
882 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
883 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
884 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
885 goto no_version_info;
888 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
889 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
890 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
892 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
893 goto no_version_info;
896 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
897 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
899 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
900 goto no_version_info;
903 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
904 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
906 int section_table_bytes;
908 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
909 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
910 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
911 /* At this point, we assume the file is in error. It still could be somthing
912 * else besides a PE file, but it unlikely at this point.
917 /* get the section table */
918 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
919 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
921 if ((buf=malloc(section_table_bytes)) == NULL) {
922 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
923 fname, section_table_bytes));
927 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
928 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
933 /* Iterate the section table looking for the resource section ".rsrc" */
934 for (i = 0; i < num_sections; i++) {
935 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
937 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
938 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
939 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
942 if ((buf=malloc(section_bytes)) == NULL) {
943 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
944 fname, section_bytes));
948 /* Seek to the start of the .rsrc section info */
949 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
950 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
955 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
956 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
961 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
962 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
963 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
964 /* Align to next long address */
965 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
967 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
968 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
969 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
971 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
972 fname, *major, *minor,
973 (*major>>16)&0xffff, *major&0xffff,
974 (*minor>>16)&0xffff, *minor&0xffff));
983 /* Version info not found, fall back to origin date/time */
984 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
988 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
989 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
990 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
991 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
992 /* At this point, we assume the file is in error. It still could be somthing
993 * else besides a NE file, but it unlikely at this point. */
997 /* Allocate a bit more space to speed up things */
999 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
1000 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1001 fname, PE_HEADER_SIZE));
1005 /* This is a HACK! I got tired of trying to sort through the messy
1006 * 'NE' file format. If anyone wants to clean this up please have at
1007 * it, but this works. 'NE' files will eventually fade away. JRR */
1008 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1009 /* Cover case that should not occur in a well formed 'NE' .dll file */
1010 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1012 for(i=0; i<byte_count; i++) {
1013 /* Fast skip past data that can't possibly match */
1014 if (buf[i] != 'V') continue;
1016 /* Potential match data crosses buf boundry, move it to beginning
1017 * of buf, and fill the buf with as much as it will hold. */
1018 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1021 memcpy(buf, &buf[i], byte_count-i);
1022 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1023 (byte_count-i))) < 0) {
1025 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1030 byte_count = bc + (byte_count - i);
1031 if (byte_count<VS_VERSION_INFO_SIZE) break;
1036 /* Check that the full signature string and the magic number that
1037 * follows exist (not a perfect solution, but the chances that this
1038 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1039 * twice, as it is simpler to read the code. */
1040 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1041 /* Compute skip alignment to next long address */
1042 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1043 sizeof(VS_SIGNATURE)) & 3;
1044 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1046 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1047 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1048 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1049 fname, *major, *minor,
1050 (*major>>16)&0xffff, *major&0xffff,
1051 (*minor>>16)&0xffff, *minor&0xffff));
1058 /* Version info not found, fall back to origin date/time */
1059 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1064 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1065 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1066 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1077 /****************************************************************************
1078 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1079 share one or more files. During the MS installation process files are checked
1080 to insure that only a newer version of a shared file is installed over an
1081 older version. There are several possibilities for this comparison. If there
1082 is no previous version, the new one is newer (obviously). If either file is
1083 missing the version info structure, compare the creation date (on Unix use
1084 the modification date). Otherwise chose the numerically larger version number.
1085 ****************************************************************************/
1086 static int file_version_is_newer(connection_struct *conn, fstring new_file,
1089 BOOL use_version = True;
1094 time_t new_create_time;
1098 time_t old_create_time;
1102 files_struct *fsp = NULL;
1104 SMB_STRUCT_STAT stat_buf;
1108 ZERO_STRUCT(stat_buf);
1109 new_create_time = (time_t)0;
1110 old_create_time = (time_t)0;
1112 /* Get file version info (if available) for previous file (if it exists) */
1113 pstrcpy(filepath, old_file);
1115 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1117 fsp = open_file_shared(conn, filepath, &stat_buf,
1118 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1119 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1120 0, 0, &access_mode, &action);
1122 /* Old file not found, so by definition new file is in fact newer */
1123 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1128 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1129 if (ret == -1) goto error_exit;
1132 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1134 use_version = False;
1135 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1136 old_create_time = st.st_mtime;
1137 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1140 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1144 /* Get file version info (if available) for new file */
1145 pstrcpy(filepath, new_file);
1146 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1148 fsp = open_file_shared(conn, filepath, &stat_buf,
1149 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1150 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1151 0, 0, &access_mode, &action);
1153 /* New file not found, this shouldn't occur if the caller did its job */
1154 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1159 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1160 if (ret == -1) goto error_exit;
1163 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1165 use_version = False;
1166 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1167 new_create_time = st.st_mtime;
1168 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1171 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1175 /* Compare versions and choose the larger version number */
1176 if (new_major > old_major ||
1177 (new_major == old_major && new_minor > old_minor)) {
1179 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1183 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1188 /* Compare modification time/dates and choose the newest time/date */
1189 if (new_create_time > old_create_time) {
1190 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1194 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1203 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1208 /****************************************************************************
1209 ****************************************************************************/
1210 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1212 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1213 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1214 fstring architecture;
1220 connection_struct *conn;
1223 struct passwd *pass;
1229 memset(inbuf, '\0', sizeof(inbuf));
1230 memset(outbuf, '\0', sizeof(outbuf));
1233 driver=driver_abstract.info_3;
1234 else if (level==6) {
1235 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1236 driver = &converted_driver;
1238 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1242 get_short_archi(architecture, driver->environment);
1245 pass = sys_getpwuid(user->uid);
1247 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1248 (unsigned int)user->uid ));
1254 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1255 fstrcpy(user_name, pass->pw_name );
1256 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1258 /* Null password is ok - we are already an authenticated user... */
1260 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1263 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1264 *perr = (uint32)ecode;
1269 * Save who we are - we are temporarily becoming the connection user.
1274 if (!become_user(conn, conn->vuid)) {
1275 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1281 * make the directories version and version\driver_name
1282 * under the architecture directory.
1284 DEBUG(5,("Creating first directory\n"));
1285 slprintf(new_dir, sizeof(new_dir), "%s/%d", architecture, driver->cversion);
1286 mkdir_internal(conn, inbuf, outbuf, new_dir);
1288 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1289 * listed for this driver which has already been moved, skip it (note:
1290 * drivers may list the same file name several times. Then check if the
1291 * file already exists in archi\cversion\, if so, check that the version
1292 * info (or time stamps if version info is unavailable) is newer (or the
1293 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1294 * Otherwise, delete the file.
1296 * If a file is not moved to archi\cversion\ because of an error, all the
1297 * rest of the 'unmoved' driver files are removed from archi\. If one or
1298 * more of the driver's files was already moved to archi\cversion\, it
1299 * potentially leaves the driver in a partially updated state. Version
1300 * trauma will most likely occur if an client attempts to use any printer
1301 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1302 * done is appropriate... later JRR
1305 DEBUG(5,("Moving files now !\n"));
1307 if (driver->driverpath && strlen(driver->driverpath)) {
1308 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->driverpath);
1309 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->driverpath);
1310 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1311 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1312 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1313 new_name, old_name));
1314 *perr = (uint32)SVAL(outbuf,smb_err);
1315 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1320 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1323 if (driver->datafile && strlen(driver->datafile)) {
1324 if (!strequal(driver->datafile, driver->driverpath)) {
1325 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->datafile);
1326 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->datafile);
1327 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1328 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1329 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1330 new_name, old_name));
1331 *perr = (uint32)SVAL(outbuf,smb_err);
1332 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1337 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1341 if (driver->configfile && strlen(driver->configfile)) {
1342 if (!strequal(driver->configfile, driver->driverpath) &&
1343 !strequal(driver->configfile, driver->datafile)) {
1344 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->configfile);
1345 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->configfile);
1346 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1347 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1348 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1349 new_name, old_name));
1350 *perr = (uint32)SVAL(outbuf,smb_err);
1351 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1356 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1360 if (driver->helpfile && strlen(driver->helpfile)) {
1361 if (!strequal(driver->helpfile, driver->driverpath) &&
1362 !strequal(driver->helpfile, driver->datafile) &&
1363 !strequal(driver->helpfile, driver->configfile)) {
1364 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->helpfile);
1365 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->helpfile);
1366 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1367 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1368 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1369 new_name, old_name));
1370 *perr = (uint32)SVAL(outbuf,smb_err);
1371 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1376 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1380 if (driver->dependentfiles) {
1381 for (i=0; *driver->dependentfiles[i]; i++) {
1382 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1383 !strequal(driver->dependentfiles[i], driver->datafile) &&
1384 !strequal(driver->dependentfiles[i], driver->configfile) &&
1385 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1387 for (j=0; j < i; j++) {
1388 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1393 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->dependentfiles[i]);
1394 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->dependentfiles[i]);
1395 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1396 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1397 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1398 new_name, old_name));
1399 *perr = (uint32)SVAL(outbuf,smb_err);
1400 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1405 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1411 close_cnum(conn, user->vuid);
1414 return ver == -1 ? False : True;
1417 /****************************************************************************
1418 ****************************************************************************/
1419 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1422 fstring architecture;
1428 TDB_DATA kbuf, dbuf;
1430 get_short_archi(architecture, driver->environment);
1432 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1433 * \\server is added in the rpc server layer.
1434 * It does make sense to NOT store the server's name in the printer TDB.
1437 slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
1439 /* .inf files do not always list a file for each of the four standard files.
1440 * Don't prepend a path to a null filename, or client claims:
1441 * "The server on which the printer resides does not have a suitable
1442 * <printer driver name> printer driver installed. Click OK if you
1443 * wish to install the driver on your local machine."
1445 if (strlen(driver->driverpath)) {
1446 fstrcpy(temp_name, driver->driverpath);
1447 slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
1450 if (strlen(driver->datafile)) {
1451 fstrcpy(temp_name, driver->datafile);
1452 slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
1455 if (strlen(driver->configfile)) {
1456 fstrcpy(temp_name, driver->configfile);
1457 slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
1460 if (strlen(driver->helpfile)) {
1461 fstrcpy(temp_name, driver->helpfile);
1462 slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
1465 if (driver->dependentfiles) {
1466 for (i=0; *driver->dependentfiles[i]; i++) {
1467 fstrcpy(temp_name, driver->dependentfiles[i]);
1468 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
1472 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1473 dos_to_unix(key, True); /* Convert key to unix-codepage */
1475 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1482 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1485 driver->environment,
1490 driver->monitorname,
1491 driver->defaultdatatype);
1493 if (driver->dependentfiles) {
1494 for (i=0; *driver->dependentfiles[i]; i++) {
1495 len += tdb_pack(buf+len, buflen-len, "f",
1496 driver->dependentfiles[i]);
1500 if (len != buflen) {
1501 buf = (char *)Realloc(buf, len);
1508 kbuf.dsize = strlen(key)+1;
1512 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1515 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1521 /****************************************************************************
1522 ****************************************************************************/
1523 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1525 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1528 info3.cversion = driver->version;
1529 fstrcpy(info3.name,driver->name);
1530 fstrcpy(info3.environment,driver->environment);
1531 fstrcpy(info3.driverpath,driver->driverpath);
1532 fstrcpy(info3.datafile,driver->datafile);
1533 fstrcpy(info3.configfile,driver->configfile);
1534 fstrcpy(info3.helpfile,driver->helpfile);
1535 fstrcpy(info3.monitorname,driver->monitorname);
1536 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1537 info3.dependentfiles = driver->dependentfiles;
1539 return add_a_printer_driver_3(&info3);
1543 /****************************************************************************
1544 ****************************************************************************/
1545 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1547 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1551 fstrcpy(info.name, in_prt);
1552 fstrcpy(info.defaultdatatype, "RAW");
1554 fstrcpy(info.driverpath, "");
1555 fstrcpy(info.datafile, "");
1556 fstrcpy(info.configfile, "");
1557 fstrcpy(info.helpfile, "");
1559 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1560 return ERROR_NOT_ENOUGH_MEMORY;
1562 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1563 fstrcpy(info.dependentfiles[0], "");
1565 *info_ptr = memdup(&info, sizeof(info));
1570 /****************************************************************************
1571 ****************************************************************************/
1572 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1574 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1575 TDB_DATA kbuf, dbuf;
1576 fstring architecture;
1581 ZERO_STRUCT(driver);
1583 get_short_archi(architecture, in_arch);
1585 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1587 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1590 kbuf.dsize = strlen(key)+1;
1592 dbuf = tdb_fetch(tdb, kbuf);
1594 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1596 if (!dbuf.dptr) return 5;
1598 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1607 driver.defaultdatatype);
1610 while (len < dbuf.dsize) {
1611 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1612 sizeof(fstring)*(i+2));
1613 if (driver.dependentfiles == NULL)
1616 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1617 &driver.dependentfiles[i]);
1620 if (driver.dependentfiles != NULL)
1621 fstrcpy(driver.dependentfiles[i], "");
1623 safe_free(dbuf.dptr);
1625 if (len != dbuf.dsize) {
1626 if (driver.dependentfiles != NULL)
1627 safe_free(driver.dependentfiles);
1629 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1632 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1637 /****************************************************************************
1638 ****************************************************************************/
1639 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1641 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1647 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1648 DEBUG(10,("driver key: [%s]\n", key));
1651 kbuf.dsize = strlen(key)+1;
1652 if (!tdb_exists(tdb, kbuf)) return False;
1655 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1657 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1658 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1659 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1660 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1661 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1662 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1663 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1665 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1666 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1667 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1669 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1670 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1671 pstrcat(line, info3->configfile);
1673 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1674 pstrcat(line, info3->datafile);
1676 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1677 pstrcat(line, info3->helpfile);
1679 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1680 pstrcat(line, info3->monitorname);
1682 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1685 for (i=0; info3->dependentfiles &&
1686 *info3->dependentfiles[i]; i++) {
1687 if (i) pstrcat(line, ","); /* don't end in a "," */
1688 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1689 pstrcat(line, info3->dependentfiles[i]);
1697 /****************************************************************************
1698 debugging function, dump at level 6 the struct in the logs
1699 ****************************************************************************/
1700 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1703 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1706 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1712 if (driver.info_3 == NULL)
1715 info3=driver.info_3;
1717 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1718 DEBUGADD(106,("name:[%s]\n", info3->name));
1719 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1720 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1721 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1722 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1723 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1724 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1725 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1727 for (i=0; info3->dependentfiles &&
1728 *info3->dependentfiles[i]; i++) {
1729 DEBUGADD(106,("dependentfile:[%s]\n",
1730 info3->dependentfiles[i]));
1737 DEBUGADD(1,("Level not implemented\n"));
1745 /****************************************************************************
1746 ****************************************************************************/
1747 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1751 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1753 if (!nt_devmode) return len;
1755 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1756 nt_devmode->devicename,
1757 nt_devmode->formname,
1759 nt_devmode->specversion,
1760 nt_devmode->driverversion,
1762 nt_devmode->driverextra,
1763 nt_devmode->orientation,
1764 nt_devmode->papersize,
1765 nt_devmode->paperlength,
1766 nt_devmode->paperwidth,
1769 nt_devmode->defaultsource,
1770 nt_devmode->printquality,
1773 nt_devmode->yresolution,
1774 nt_devmode->ttoption,
1775 nt_devmode->collate,
1776 nt_devmode->logpixels,
1779 nt_devmode->bitsperpel,
1780 nt_devmode->pelswidth,
1781 nt_devmode->pelsheight,
1782 nt_devmode->displayflags,
1783 nt_devmode->displayfrequency,
1784 nt_devmode->icmmethod,
1785 nt_devmode->icmintent,
1786 nt_devmode->mediatype,
1787 nt_devmode->dithertype,
1788 nt_devmode->reserved1,
1789 nt_devmode->reserved2,
1790 nt_devmode->panningwidth,
1791 nt_devmode->panningheight,
1792 nt_devmode->private);
1795 if (nt_devmode->private) {
1796 len += tdb_pack(buf+len, buflen-len, "B",
1797 nt_devmode->driverextra,
1798 nt_devmode->private);
1801 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1806 /****************************************************************************
1807 ****************************************************************************/
1808 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1812 while (param != NULL) {
1813 len += tdb_pack(buf+len, buflen-len, "pfdB",
1822 len += tdb_pack(buf+len, buflen-len, "p", param);
1828 /****************************************************************************
1829 delete a printer - this just deletes the printer info file, any open
1830 handles are not affected
1831 ****************************************************************************/
1832 uint32 del_a_printer(char *sharename)
1837 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
1838 dos_to_unix(key, True); /* Convert key to unix-codepage */
1841 kbuf.dsize=strlen(key)+1;
1843 tdb_delete(tdb, kbuf);
1847 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1848 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1849 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1850 /****************************************************************************
1851 ****************************************************************************/
1852 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1856 int buflen, len, ret;
1857 TDB_DATA kbuf, dbuf;
1860 * in addprinter: no servername and the printer is the name
1861 * in setprinter: servername is \\server
1862 * and printer is \\server\\printer
1864 * Samba manages only local printers.
1865 * we currently don't support things like path=\\other_server\printer
1868 if (info->servername[0]!='\0') {
1869 trim_string(info->printername, info->servername, NULL);
1870 trim_string(info->printername, "\\", NULL);
1871 info->servername[0]='\0';
1875 * JFM: one day I'll forget.
1876 * below that's info->portname because that's the SAMBA sharename
1877 * and I made NT 'thinks' it's the portname
1878 * the info->sharename is the thing you can name when you add a printer
1879 * that's the short-name when you create shared printer for 95/98
1880 * So I've made a limitation in SAMBA: you can only have 1 printer model
1881 * behind a SAMBA share.
1889 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1892 info->default_priority,
1909 info->printprocessor,
1913 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1915 len += pack_specifics(info->specific, buf+len, buflen-len);
1917 if (buflen != len) {
1918 buf = (char *)Realloc(buf, len);
1924 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, info->sharename);
1925 dos_to_unix(key, True); /* Convert key to unix-codepage */
1928 kbuf.dsize = strlen(key)+1;
1932 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1935 DEBUG(8, ("error updating printer to tdb on disk\n"));
1939 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1940 info->sharename, info->drivername, info->portname, len));
1946 /****************************************************************************
1947 ****************************************************************************/
1948 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1950 NT_PRINTER_PARAM *current;
1952 DEBUG(108,("add_a_specific_param\n"));
1954 (*param)->next=NULL;
1956 if (info_2->specific == NULL)
1958 info_2->specific=*param;
1962 current=info_2->specific;
1963 while (current->next != NULL) {
1964 current=current->next;
1966 current->next=*param;
1972 /****************************************************************************
1973 ****************************************************************************/
1974 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1976 NT_PRINTER_PARAM *current;
1977 NT_PRINTER_PARAM *previous;
1979 current=info_2->specific;
1982 if (current==NULL) return (False);
1984 if ( !strcmp(current->value, param->value) &&
1985 (strlen(current->value)==strlen(param->value)) ) {
1986 DEBUG(109,("deleting first value\n"));
1987 info_2->specific=current->next;
1988 safe_free(current->data);
1990 DEBUG(109,("deleted first value\n"));
1994 current=previous->next;
1996 while ( current!=NULL ) {
1997 if (!strcmp(current->value, param->value) &&
1998 strlen(current->value)==strlen(param->value) ) {
1999 DEBUG(109,("deleting current value\n"));
2000 previous->next=current->next;
2001 safe_free(current->data);
2003 DEBUG(109,("deleted current value\n"));
2007 previous=previous->next;
2008 current=current->next;
2013 /****************************************************************************
2014 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2015 ****************************************************************************/
2016 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2018 NT_PRINTER_PARAM *param = *param_ptr;
2023 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2026 safe_free(param->data);
2032 /****************************************************************************
2033 Malloc and return an NT devicemode.
2034 ****************************************************************************/
2036 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2039 * should I init this ones ???
2040 nt_devmode->devicename
2044 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2046 if (nt_devmode == NULL) {
2047 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2051 ZERO_STRUCTP(nt_devmode);
2053 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2054 fstrcpy(nt_devmode->devicename, adevice);
2056 fstrcpy(nt_devmode->formname, "Letter");
2058 nt_devmode->specversion = 0x0401;
2059 nt_devmode->driverversion = 0x0400;
2060 nt_devmode->size = 0x00DC;
2061 nt_devmode->driverextra = 0x0000;
2062 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2063 DEFAULTSOURCE | COPIES | SCALE |
2064 PAPERSIZE | ORIENTATION;
2065 nt_devmode->orientation = 1;
2066 nt_devmode->papersize = PAPER_LETTER;
2067 nt_devmode->paperlength = 0;
2068 nt_devmode->paperwidth = 0;
2069 nt_devmode->scale = 0x64;
2070 nt_devmode->copies = 01;
2071 nt_devmode->defaultsource = BIN_FORMSOURCE;
2072 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2073 nt_devmode->color = COLOR_MONOCHROME;
2074 nt_devmode->duplex = DUP_SIMPLEX;
2075 nt_devmode->yresolution = 0;
2076 nt_devmode->ttoption = TT_SUBDEV;
2077 nt_devmode->collate = COLLATE_FALSE;
2078 nt_devmode->icmmethod = 0;
2079 nt_devmode->icmintent = 0;
2080 nt_devmode->mediatype = 0;
2081 nt_devmode->dithertype = 0;
2083 /* non utilisés par un driver d'imprimante */
2084 nt_devmode->logpixels = 0;
2085 nt_devmode->bitsperpel = 0;
2086 nt_devmode->pelswidth = 0;
2087 nt_devmode->pelsheight = 0;
2088 nt_devmode->displayflags = 0;
2089 nt_devmode->displayfrequency = 0;
2090 nt_devmode->reserved1 = 0;
2091 nt_devmode->reserved2 = 0;
2092 nt_devmode->panningwidth = 0;
2093 nt_devmode->panningheight = 0;
2095 nt_devmode->private = NULL;
2099 /****************************************************************************
2100 Deepcopy an NT devicemode.
2101 ****************************************************************************/
2103 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2105 NT_DEVICEMODE *new_nt_devicemode = NULL;
2107 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2108 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2112 new_nt_devicemode->private = NULL;
2113 if (nt_devicemode->private != NULL) {
2114 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2115 safe_free(new_nt_devicemode);
2116 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2121 return new_nt_devicemode;
2124 /****************************************************************************
2125 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2126 ****************************************************************************/
2128 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2130 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2132 if(nt_devmode == NULL)
2135 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2137 if(nt_devmode->private)
2138 safe_free(nt_devmode->private);
2140 safe_free(nt_devmode);
2141 *devmode_ptr = NULL;
2144 /****************************************************************************
2145 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2146 ****************************************************************************/
2147 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2149 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2150 NT_PRINTER_PARAM *param_ptr;
2155 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2157 free_nt_devicemode(&info->devmode);
2159 for(param_ptr = info->specific; param_ptr; ) {
2160 NT_PRINTER_PARAM *tofree = param_ptr;
2162 param_ptr = param_ptr->next;
2163 free_nt_printer_param(&tofree);
2166 safe_free(*info_ptr);
2171 /****************************************************************************
2172 ****************************************************************************/
2173 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2177 NT_DEVICEMODE devmode;
2179 ZERO_STRUCT(devmode);
2181 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2183 if (!*nt_devmode) return len;
2185 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2189 &devmode.specversion,
2190 &devmode.driverversion,
2192 &devmode.driverextra,
2193 &devmode.orientation,
2195 &devmode.paperlength,
2196 &devmode.paperwidth,
2199 &devmode.defaultsource,
2200 &devmode.printquality,
2203 &devmode.yresolution,
2209 &devmode.bitsperpel,
2211 &devmode.pelsheight,
2212 &devmode.displayflags,
2213 &devmode.displayfrequency,
2217 &devmode.dithertype,
2220 &devmode.panningwidth,
2221 &devmode.panningheight,
2224 if (devmode.private) {
2225 /* the len in tdb_unpack is an int value and
2226 * devmode.driverextra is only a short
2228 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2229 devmode.driverextra=(uint16)extra_len;
2231 /* check to catch an invalid TDB entry so we don't segfault */
2232 if (devmode.driverextra == 0) {
2233 devmode.private = NULL;
2237 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2239 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2240 if (devmode.private)
2241 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2246 /****************************************************************************
2247 ****************************************************************************/
2248 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2251 NT_PRINTER_PARAM param, *p;
2256 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2259 len += tdb_unpack(buf+len, buflen-len, "fdB",
2265 *list = memdup(¶m, sizeof(param));
2267 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2273 static void map_to_os2_driver(fstring drivername)
2275 static BOOL initialised=False;
2276 static fstring last_from,last_to;
2277 char *mapfile = lp_os2_driver_map();
2278 char **lines = NULL;
2282 if (!strlen(drivername))
2289 *last_from = *last_to = 0;
2293 if (strequal(drivername,last_from)) {
2294 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2295 fstrcpy(drivername,last_to);
2299 lines = file_lines_load(mapfile, &numlines, True);
2300 if (numlines == 0) {
2301 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2305 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2307 for( i = 0; i < numlines; i++) {
2308 char *nt_name = lines[i];
2309 char *os2_name = strchr(nt_name,'=');
2316 while (isspace(*nt_name))
2319 if (!*nt_name || strchr("#;",*nt_name))
2323 int l = strlen(nt_name);
2324 while (l && isspace(nt_name[l-1])) {
2330 while (isspace(*os2_name))
2334 int l = strlen(os2_name);
2335 while (l && isspace(os2_name[l-1])) {
2341 if (strequal(nt_name,drivername)) {
2342 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2343 fstrcpy(last_from,drivername);
2344 fstrcpy(last_to,os2_name);
2345 fstrcpy(drivername,os2_name);
2346 file_lines_free(lines);
2351 file_lines_free(lines);
2354 /****************************************************************************
2355 get a default printer info 2 struct
2356 ****************************************************************************/
2357 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2359 extern pstring global_myname;
2361 NT_PRINTER_INFO_LEVEL_2 info;
2365 snum = lp_servicenumber(sharename);
2367 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2368 slprintf(info.printername, sizeof(info.printername), "\\\\%s\\%s",
2369 global_myname, sharename);
2370 fstrcpy(info.sharename, sharename);
2371 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2372 fstrcpy(info.drivername, lp_printerdriver(snum));
2374 if (!*info.drivername)
2375 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2377 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2379 pstrcpy(info.comment, "");
2380 fstrcpy(info.printprocessor, "winprint");
2381 fstrcpy(info.datatype, "RAW");
2383 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2384 | PRINTER_ATTRIBUTE_LOCAL \
2385 | PRINTER_ATTRIBUTE_RAW_ONLY \
2386 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2388 info.starttime = 0; /* Minutes since 12:00am GMT */
2389 info.untiltime = 0; /* Minutes since 12:00am GMT */
2391 info.default_priority = 1;
2392 info.setuptime = (uint32)time(NULL);
2394 #if 1 /* JRA - NO NOT CHANGE ! */
2395 info.devmode = NULL;
2398 * We should not return a default devicemode, as this causes
2399 * Win2K to not send the correct one on PCL drivers. It needs to
2400 * see a null devicemode so it can then overwrite the devicemode
2401 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2403 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2407 /* This will get the current RPC talloc context, but we should be
2408 passing this as a parameter... fixme... JRA ! */
2410 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2413 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2415 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2424 free_nt_devicemode(&info.devmode);
2428 /****************************************************************************
2429 ****************************************************************************/
2430 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2433 NT_PRINTER_INFO_LEVEL_2 info;
2435 TDB_DATA kbuf, dbuf;
2436 fstring printername;
2440 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
2441 dos_to_unix(key, True); /* Convert key to unix-codepage */
2444 kbuf.dsize = strlen(key)+1;
2446 dbuf = tdb_fetch(tdb, kbuf);
2448 return get_a_printer_2_default(info_ptr, sharename);
2450 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2453 &info.default_priority,
2470 info.printprocessor,
2474 /* Samba has to have shared raw drivers. */
2475 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2477 /* Restore the stripped strings. */
2478 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2479 slprintf(printername, sizeof(printername), "\\\\%s\\%s", global_myname,
2481 fstrcpy(info.printername, printername);
2483 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2484 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2486 /* This will get the current RPC talloc context, but we should be
2487 passing this as a parameter... fixme... JRA ! */
2489 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2491 /* Fix for OS/2 drivers. */
2493 if (get_remote_arch() == RA_OS2)
2494 map_to_os2_driver(info.drivername);
2496 safe_free(dbuf.dptr);
2497 *info_ptr=memdup(&info, sizeof(info));
2499 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2500 sharename, info.printername, info.drivername));
2506 /****************************************************************************
2507 debugging function, dump at level 6 the struct in the logs
2508 ****************************************************************************/
2509 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2512 NT_PRINTER_INFO_LEVEL_2 *info2;
2514 DEBUG(106,("Dumping printer at level [%d]\n", level));
2520 if (printer.info_2 == NULL)
2524 info2=printer.info_2;
2526 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2527 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2528 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2529 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2530 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2531 DEBUGADD(106,("status:[%d]\n", info2->status));
2532 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2533 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2534 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2535 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2536 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2538 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2539 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2540 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2541 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2542 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2543 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2544 DEBUGADD(106,("location:[%s]\n", info2->location));
2545 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2546 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2547 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2548 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2554 DEBUGADD(1,("Level not implemented\n"));
2562 /****************************************************************************
2563 Get the parameters we can substitute in an NT print job.
2564 ****************************************************************************/
2566 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2568 NT_PRINTER_INFO_LEVEL *printer = NULL;
2570 **printername = **sharename = **portname = '\0';
2572 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2575 fstrcpy(*printername, printer->info_2->printername);
2576 fstrcpy(*sharename, printer->info_2->sharename);
2577 fstrcpy(*portname, printer->info_2->portname);
2579 free_a_printer(&printer, 2);
2583 * The function below are the high level ones.
2584 * only those ones must be called from the spoolss code.
2588 /****************************************************************************
2589 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2590 ****************************************************************************/
2592 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2596 dump_a_printer(printer, level);
2602 printer.info_2->c_setprinter++;
2603 result=update_a_printer_2(printer.info_2);
2614 /****************************************************************************
2615 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2616 We split this out from mod_a_printer as it updates the id's and timestamps.
2617 ****************************************************************************/
2619 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2623 dump_a_printer(printer, level);
2630 * Update the changestamp.
2631 * Note we must *not* do this in mod_a_printer().
2634 time_t time_unix = time(NULL);
2635 unix_to_nt_time(&time_nt, time_unix);
2636 if (printer.info_2->changeid==time_nt.low)
2637 printer.info_2->changeid++;
2639 printer.info_2->changeid=time_nt.low;
2641 printer.info_2->c_setprinter++;
2643 result=update_a_printer_2(printer.info_2);
2654 /****************************************************************************
2655 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2656 ****************************************************************************/
2658 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2661 NT_PRINTER_INFO_LEVEL *printer = NULL;
2665 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2671 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2672 DEBUG(0,("get_a_printer: malloc fail.\n"));
2675 ZERO_STRUCTP(printer);
2676 result=get_a_printer_2(&printer->info_2, sharename);
2678 dump_a_printer(*printer, level);
2679 *pp_printer = printer;
2690 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2695 /****************************************************************************
2696 Deletes a NT_PRINTER_INFO_LEVEL struct.
2697 ****************************************************************************/
2699 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2702 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2704 DEBUG(104,("freeing a printer at level [%d]\n", level));
2706 if (printer == NULL)
2713 if (printer->info_2 != NULL)
2715 free_nt_printer_info_level_2(&printer->info_2);
2734 /****************************************************************************
2735 ****************************************************************************/
2736 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2739 DEBUG(104,("adding a printer at level [%d]\n", level));
2740 dump_a_printer_driver(driver, level);
2746 result=add_a_printer_driver_3(driver.info_3);
2752 result=add_a_printer_driver_6(driver.info_6);
2762 /****************************************************************************
2763 ****************************************************************************/
2764 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2765 fstring printername, fstring architecture, uint32 version)
2773 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2782 dump_a_printer_driver(*driver, level);
2786 /****************************************************************************
2787 ****************************************************************************/
2788 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2796 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2797 if (driver.info_3 != NULL)
2799 info3=driver.info_3;
2800 safe_free(info3->dependentfiles);
2801 ZERO_STRUCTP(info3);
2813 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2814 if (driver.info_6 != NULL)
2816 info6=driver.info_6;
2817 safe_free(info6->dependentfiles);
2818 safe_free(info6->previousnames);
2819 ZERO_STRUCTP(info6);
2836 /****************************************************************************
2837 ****************************************************************************/
2838 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2839 fstring value, uint8 **data, uint32 *type, uint32 *len)
2841 /* right now that's enough ! */
2842 NT_PRINTER_PARAM *param;
2845 param=printer.info_2->specific;
2847 while (param != NULL && i < param_index) {
2855 /* exited because it exist */
2857 StrnCpy(value, param->value, sizeof(fstring)-1);
2858 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2861 ZERO_STRUCTP(*data);
2862 memcpy(*data, param->data, param->data_len);
2863 *len=param->data_len;
2867 /****************************************************************************
2868 ****************************************************************************/
2869 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2870 fstring value, uint8 **data, uint32 *type, uint32 *len)
2872 /* right now that's enough ! */
2873 NT_PRINTER_PARAM *param;
2875 DEBUG(10, ("get_specific_param\n"));
2877 param=printer.info_2->specific;
2879 while (param != NULL)
2881 #if 1 /* JRA - I think this should be case insensitive.... */
2882 if ( strequal(value, param->value)
2884 if ( !strcmp(value, param->value)
2886 && strlen(value)==strlen(param->value))
2894 DEBUGADD(10, ("get_specific_param: found one param\n"));
2895 /* exited because it exist */
2898 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2901 memcpy(*data, param->data, param->data_len);
2902 *len=param->data_len;
2904 DEBUGADD(10, ("get_specific_param: exit true\n"));
2907 DEBUGADD(10, ("get_specific_param: exit false\n"));
2911 /****************************************************************************
2912 Store a security desc for a printer.
2913 ****************************************************************************/
2915 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2917 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2918 SEC_DESC_BUF *old_secdesc_ctr = NULL;
2920 TALLOC_CTX *mem_ctx = NULL;
2924 mem_ctx = talloc_init();
2925 if (mem_ctx == NULL)
2928 /* The old owner and group sids of the security descriptor are not
2929 present when new ACEs are added or removed by changing printer
2930 permissions through NT. If they are NULL in the new security
2931 descriptor then copy them over from the old one. */
2933 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
2934 DOM_SID *owner_sid, *group_sid;
2935 SEC_ACL *dacl, *sacl;
2936 SEC_DESC *psd = NULL;
2939 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
2941 /* Pick out correct owner and group sids */
2943 owner_sid = secdesc_ctr->sec->owner_sid ?
2944 secdesc_ctr->sec->owner_sid :
2945 old_secdesc_ctr->sec->owner_sid;
2947 group_sid = secdesc_ctr->sec->grp_sid ?
2948 secdesc_ctr->sec->grp_sid :
2949 old_secdesc_ctr->sec->grp_sid;
2951 dacl = secdesc_ctr->sec->dacl ?
2952 secdesc_ctr->sec->dacl :
2953 old_secdesc_ctr->sec->dacl;
2955 sacl = secdesc_ctr->sec->sacl ?
2956 secdesc_ctr->sec->sacl :
2957 old_secdesc_ctr->sec->sacl;
2959 /* Make a deep copy of the security descriptor */
2961 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
2962 owner_sid, group_sid,
2967 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
2970 if (!new_secdesc_ctr) {
2971 new_secdesc_ctr = secdesc_ctr;
2974 /* Store the security descriptor in a tdb */
2976 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
2977 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
2979 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
2981 status = ERROR_INVALID_FUNCTION;
2985 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2987 if (tdb_prs_store(tdb, key, &ps)==0) {
2990 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2991 status = ERROR_INVALID_FUNCTION;
2994 /* Free mallocated memory */
3000 talloc_destroy(mem_ctx);
3004 /****************************************************************************
3005 Construct a default security descriptor buffer for a printer.
3006 ****************************************************************************/
3008 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3012 SEC_ACL *psa = NULL;
3013 SEC_DESC_BUF *sdb = NULL;
3014 SEC_DESC *psd = NULL;
3017 enum SID_NAME_USE name_type;
3019 /* Create an ACE where Everyone is allowed to print */
3021 init_sec_access(&sa, PRINTER_ACE_PRINT);
3022 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3023 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3025 /* Make the security descriptor owned by the Administrators group
3026 on the PDC of the domain. */
3028 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3029 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3032 /* Backup plan - make printer owned by admins or root. This should
3033 emulate a lanman printer as security settings can't be
3036 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
3037 !lookup_name( "Administrators", &owner_sid, &name_type) &&
3038 !lookup_name( "Administrator", &owner_sid, &name_type) &&
3039 !lookup_name("root", &owner_sid, &name_type)) {
3040 sid_copy(&owner_sid, &global_sid_World);
3044 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3045 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3046 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3047 SEC_ACE_FLAG_INHERIT_ONLY);
3049 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3050 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3051 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3053 /* The ACL revision number in rpc_secdesc.h differs from the one
3054 created by NT when setting ACE entries in printer
3055 descriptors. NT4 complains about the property being edited by a
3058 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3059 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3061 NULL, psa, &sd_size);
3065 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3069 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3071 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3072 (unsigned int)sd_size));
3077 /****************************************************************************
3078 Get a security desc for a printer.
3079 ****************************************************************************/
3081 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3087 if ((temp = strchr(printername + 2, '\\'))) {
3088 printername = temp + 1;
3091 /* Fetch security descriptor from tdb */
3093 slprintf(key, sizeof(key), "SECDESC/%s", printername);
3095 if (tdb_prs_fetch(tdb, key, &ps, ctx)!=0 ||
3096 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3098 DEBUG(4,("using default secdesc for %s\n", printername));
3100 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3107 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3108 this security descriptor has been created when winbindd was
3109 down. Take ownership of security descriptor. */
3111 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3113 enum SID_NAME_USE name_type;
3115 /* Change sd owner to workgroup administrator */
3117 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3119 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3120 SEC_DESC *psd = NULL;
3125 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3127 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3129 (*secdesc_ctr)->sec->grp_sid,
3130 (*secdesc_ctr)->sec->sacl,
3131 (*secdesc_ctr)->sec->dacl,
3134 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3136 /* Swap with other one */
3138 *secdesc_ctr = new_secdesc_ctr;
3142 nt_printing_setsec(printername, *secdesc_ctr);
3146 if (DEBUGLEVEL >= 10) {
3147 SEC_ACL *acl = (*secdesc_ctr)->sec->dacl;
3150 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3151 printername, acl->num_aces));
3153 for (i = 0; i < acl->num_aces; i++) {
3156 sid_to_string(sid_str, &acl->ace[i].sid);
3158 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3159 acl->ace[i].type, acl->ace[i].flags,
3160 acl->ace[i].info.mask));
3170 1: level not implemented
3171 2: file doesn't exist
3172 3: can't allocate memory
3173 4: can't free memory
3174 5: non existant struct
3178 A printer and a printer driver are 2 different things.
3179 NT manages them separatelly, Samba does the same.
3180 Why ? Simply because it's easier and it makes sense !
3182 Now explanation: You have 3 printers behind your samba server,
3183 2 of them are the same make and model (laser A and B). But laser B
3184 has an 3000 sheet feeder and laser A doesn't such an option.
3185 Your third printer is an old dot-matrix model for the accounting :-).
3187 If the /usr/local/samba/lib directory (default dir), you will have
3188 5 files to describe all of this.
3190 3 files for the printers (1 by printer):
3193 NTprinter_accounting
3194 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3195 NTdriver_printer model X
3196 NTdriver_printer model Y
3198 jfm: I should use this comment for the text file to explain
3199 same thing for the forms BTW.
3200 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3204 /* Convert generic access rights to printer object specific access rights.
3205 It turns out that NT4 security descriptors use generic access rights and
3206 NT5 the object specific ones. */
3208 void map_printer_permissions(SEC_DESC *sd)
3212 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3213 se_map_generic(&sd->dacl->ace[i].info.mask,
3214 &printer_generic_mapping);
3218 /****************************************************************************
3219 Check a user has permissions to perform the given operation. We use the
3220 permission constants defined in include/rpc_spoolss.h to check the various
3221 actions we perform when checking printer access.
3223 PRINTER_ACCESS_ADMINISTER:
3224 print_queue_pause, print_queue_resume, update_printer_sec,
3225 update_printer, spoolss_addprinterex_level_2,
3226 _spoolss_setprinterdata
3231 JOB_ACCESS_ADMINISTER:
3232 print_job_delete, print_job_pause, print_job_resume,
3235 ****************************************************************************/
3236 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3238 SEC_DESC_BUF *secdesc = NULL;
3239 uint32 access_granted, status;
3242 TALLOC_CTX *mem_ctx = NULL;
3243 extern struct current_user current_user;
3245 /* If user is NULL then use the current_user structure */
3247 if (!user) user = ¤t_user;
3249 /* Always allow root or printer admins to do anything */
3251 if (user->uid == 0 ||
3252 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3256 /* Get printer name */
3258 pname = PRINTERNAME(snum);
3260 if (!pname || !*pname) {
3265 /* Get printer security descriptor */
3267 if(!(mem_ctx = talloc_init())) {
3272 nt_printing_getsec(mem_ctx, pname, &secdesc);
3274 if (access_type == JOB_ACCESS_ADMINISTER) {
3275 SEC_DESC_BUF *parent_secdesc = secdesc;
3277 /* Create a child security descriptor to check permissions
3278 against. This is because print jobs are child objects
3279 objects of a printer. */
3281 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3283 /* Now this is the bit that really confuses me. The access
3284 type needs to be changed from JOB_ACCESS_ADMINISTER to
3285 PRINTER_ACCESS_ADMINISTER for this to work. Something
3286 to do with the child (job) object becoming like a
3289 access_type = PRINTER_ACCESS_ADMINISTER;
3294 map_printer_permissions(secdesc->sec);
3296 result = se_access_check(secdesc->sec, user, access_type,
3297 &access_granted, &status);
3299 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3301 talloc_destroy(mem_ctx);
3309 /****************************************************************************
3310 Check the time parameters allow a print operation.
3311 *****************************************************************************/
3313 BOOL print_time_access_check(int snum)
3315 NT_PRINTER_INFO_LEVEL *printer = NULL;
3317 time_t now = time(NULL);
3321 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3324 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3328 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3330 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3333 free_a_printer(&printer, 2);
3341 /****************************************************************************
3342 Attempt to write a default device.
3343 *****************************************************************************/
3345 uint32 printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3347 NT_PRINTER_INFO_LEVEL *printer = NULL;
3352 * Don't bother if no default devicemode was sent.
3355 if (printer_default->devmode_cont.devmode == NULL)
3358 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3359 return ERROR_ACCESS_DENIED;
3362 * Just ignore it if we already have a devmode.
3365 if (printer->info_2->devmode != NULL)
3369 * We don't have a devicemode and we're trying to write
3370 * one. Check we have the access needed.
3372 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3374 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3375 PRINTER_ACCESS_ADMINISTER) {
3376 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3377 result = ERROR_ACCESS_DENIED;
3381 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3382 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3383 lp_servicename(snum) ));
3384 result = ERROR_ACCESS_DENIED;
3385 /*result = NT_STATUS_NO_PROBLEMO;*/
3389 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3392 * Convert the on the wire devicemode format to the internal one.
3395 if (!convert_devicemode(printer->info_2->printername,
3396 printer_default->devmode_cont.devmode,
3397 &printer->info_2->devmode)) {
3398 result = ERROR_NOT_ENOUGH_MEMORY;
3403 * Finally write back to the tdb.
3406 if (add_a_printer(*printer, 2)!=0) {
3407 result = ERROR_ACCESS_DENIED;
3413 free_a_printer(&printer, 2);