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 static TDB_CONTEXT *tdb_forms; /* used for forms files */
32 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
33 static TDB_CONTEXT *tdb_printers; /* used for printers files */
35 #define FORMS_PREFIX "FORMS/"
36 #define DRIVERS_PREFIX "DRIVERS/"
37 #define PRINTERS_PREFIX "PRINTERS/"
38 #define SECDESC_PREFIX "SECDESC/"
40 #define NTDRIVERS_DATABASE_VERSION_1 1
41 #define NTDRIVERS_DATABASE_VERSION_2 2
43 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_2
45 /* Map generic permissions to printer object specific permissions */
47 struct generic_mapping printer_generic_mapping = {
54 /* We need one default form to support our default printer. Msoft adds the
55 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
56 array index). Letter is always first, so (for the current code) additions
57 always put things in the correct order. */
58 static nt_forms_struct default_forms[] = {
59 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
60 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
61 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
62 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
63 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
64 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
65 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
66 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
67 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
68 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
69 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
70 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
71 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
72 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
73 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
74 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
75 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
76 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
77 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
78 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
79 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
80 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
81 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
82 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
83 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
84 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
85 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
86 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
87 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
88 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
89 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
90 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
91 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
92 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
93 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
94 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
95 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
96 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
97 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
98 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
99 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
100 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
101 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
102 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
103 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
104 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
105 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
106 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
107 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
108 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
109 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
110 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
111 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
112 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
113 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
114 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
115 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
116 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
117 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
118 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
119 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
120 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
121 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
122 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
123 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
124 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
125 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
126 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
127 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
128 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
129 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
130 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
131 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
132 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
133 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
134 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
135 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
136 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
137 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
138 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
139 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
140 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
141 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
142 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
143 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
144 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
145 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
146 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
147 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
148 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
149 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
150 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
151 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
152 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
153 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
154 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
155 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
156 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
157 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
158 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
159 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
160 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
161 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
162 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
163 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
164 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
165 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
166 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
167 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
168 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
169 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
170 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
171 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
172 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
173 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
174 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
175 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
176 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
179 static void upgrade_to_version_2(void)
181 TDB_DATA kbuf, newkey, dbuf;
183 DEBUG(0,("upgrade_to_version_2:upgrading to version 2\n"));
185 for (kbuf = tdb_firstkey(tdb_drivers);
187 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
188 dbuf = tdb_fetch(tdb_drivers, kbuf);
190 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
191 DEBUG(0,("upgrade_to_version_2:moving form\n"));
192 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
193 tdb_delete(tdb_drivers, kbuf);
196 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
197 DEBUG(0,("upgrade_to_version_2:moving printer\n"));
198 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) break;
199 tdb_delete(tdb_drivers, kbuf);
202 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
203 DEBUG(0,("upgrade_to_version_2:moving secdesc\n"));
204 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) break;
205 tdb_delete(tdb_drivers, kbuf);
208 safe_free(dbuf.dptr);
216 /****************************************************************************
217 open the NT printing tdb
218 ****************************************************************************/
219 BOOL nt_printing_init(void)
221 static pid_t local_pid;
222 char *vstring = "INFO/version";
224 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid()) return True;
226 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
228 DEBUG(0,("Failed to open nt drivers database %s (%s)\n",
229 lock_path("ntdrivers.tdb"), strerror(errno) ));
233 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
235 DEBUG(0,("Failed to open nt printers database %s (%s)\n",
236 lock_path("ntprinters.tdb"), strerror(errno) ));
240 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
242 DEBUG(0,("Failed to open nt forms database %s (%s)\n",
243 lock_path("ntforms.tdb"), strerror(errno) ));
247 local_pid = sys_getpid();
249 /* handle a Samba upgrade */
250 tdb_lock_bystring(tdb_drivers, vstring);
251 if (tdb_fetch_int(tdb_drivers, vstring) != NTDRIVERS_DATABASE_VERSION) {
253 if (tdb_fetch_int(tdb_drivers, vstring) == NTDRIVERS_DATABASE_VERSION_1)
254 upgrade_to_version_2();
256 tdb_traverse(tdb_drivers, (tdb_traverse_func)tdb_delete, NULL);
258 tdb_store_int(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
260 tdb_unlock_bystring(tdb_drivers, vstring);
263 tdb_create_index(tdb, "DRIVERS/");
265 tdb_lookup_index(tdb, "DRIVERS/", &list, &count);
267 DEBUG(0,("nt_printing_init: got %d drivers\n", count));
269 for (i=0;i<count;i++)
270 DEBUG(0,("nt_printing_init: [%s]\n", list[i]));
275 /****************************************************************************
276 get builtin form struct list
277 ****************************************************************************/
278 int get_builtin_ntforms(nt_forms_struct **list)
280 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
281 return sizeof(default_forms) / sizeof(default_forms[0]);
284 /****************************************************************************
285 get a builtin form struct
286 ****************************************************************************/
288 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
292 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
293 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
294 count = sizeof(default_forms) / sizeof(default_forms[0]);
295 for (i=0;i<count;i++) {
296 if (strequal(form_name,default_forms[i].name)) {
297 DEBUGADD(6,("Found builtin form %s \n", form_name));
298 memcpy(form,&default_forms[i],sizeof(*form));
306 /****************************************************************************
307 get a form struct list
308 ****************************************************************************/
309 int get_ntforms(nt_forms_struct **list)
311 TDB_DATA kbuf, newkey, dbuf;
312 nt_forms_struct form;
317 for (kbuf = tdb_firstkey(tdb_forms);
319 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
320 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
322 dbuf = tdb_fetch(tdb_forms, kbuf);
323 if (!dbuf.dptr) continue;
325 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
326 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
327 &i, &form.flag, &form.width, &form.length, &form.left,
328 &form.top, &form.right, &form.bottom);
329 safe_free(dbuf.dptr);
330 if (ret != dbuf.dsize) continue;
332 *list = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
334 DEBUG(0,("get_ntforms: Realloc fail.\n"));
345 /****************************************************************************
346 write a form struct list
347 ****************************************************************************/
348 int write_ntforms(nt_forms_struct **list, int number)
355 for (i=0;i<number;i++) {
356 /* save index, so list is rebuilt in correct order */
357 len = tdb_pack(buf, sizeof(buf), "dddddddd",
358 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
359 (*list)[i].left, (*list)[i].top, (*list)[i].right,
361 if (len > sizeof(buf)) break;
362 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
363 kbuf.dsize = strlen(key)+1;
367 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
373 /****************************************************************************
374 add a form struct at the end of the list
375 ****************************************************************************/
376 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
383 * NT tries to add forms even when
384 * they are already in the base
385 * only update the values if already present
390 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
391 for (n=0; n<*count; n++) {
392 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
393 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
400 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
402 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
406 (*list)[n].flag=form->flags;
407 (*list)[n].width=form->size_x;
408 (*list)[n].length=form->size_y;
409 (*list)[n].left=form->left;
410 (*list)[n].top=form->top;
411 (*list)[n].right=form->right;
412 (*list)[n].bottom=form->bottom;
417 /****************************************************************************
418 delete a named form struct
419 ****************************************************************************/
420 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
429 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
431 for (n=0; n<*count; n++) {
432 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
433 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
439 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
440 *ret = ERROR_INVALID_PARAMETER;
444 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
445 kbuf.dsize = strlen(key)+1;
447 if (tdb_delete(tdb_forms, kbuf) != 0) {
448 *ret = ERROR_NOT_ENOUGH_MEMORY;
455 /****************************************************************************
457 ****************************************************************************/
458 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
462 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
464 DEBUG(106, ("[%s]\n", form_name));
465 for (n=0; n<count; n++)
467 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
468 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
472 if (n==count) return;
474 (*list)[n].flag=form->flags;
475 (*list)[n].width=form->size_x;
476 (*list)[n].length=form->size_y;
477 (*list)[n].left=form->left;
478 (*list)[n].top=form->top;
479 (*list)[n].right=form->right;
480 (*list)[n].bottom=form->bottom;
483 /****************************************************************************
484 get the nt drivers list
486 traverse the database and look-up the matching names
487 ****************************************************************************/
488 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
493 TDB_DATA kbuf, newkey;
495 get_short_archi(short_archi, architecture);
496 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
498 for (kbuf = tdb_firstkey(tdb_drivers);
500 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
501 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
503 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
506 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
513 /****************************************************************************
514 function to do the mapping between the long architecture name and
516 ****************************************************************************/
517 BOOL get_short_archi(char *short_archi, char *long_archi)
524 struct table archi_table[]=
526 {"Windows 4.0", "WIN40" },
527 {"Windows NT x86", "W32X86" },
528 {"Windows NT R4000", "W32MIPS" },
529 {"Windows NT Alpha_AXP", "W32ALPHA" },
530 {"Windows NT PowerPC", "W32PPC" },
536 DEBUG(107,("Getting architecture dependant directory\n"));
539 } while ( (archi_table[i].long_archi!=NULL ) &&
540 StrCaseCmp(long_archi, archi_table[i].long_archi) );
542 if (archi_table[i].long_archi==NULL) {
543 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
547 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
549 DEBUGADD(108,("index: [%d]\n", i));
550 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
551 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
556 /****************************************************************************
557 Determine the correct cVersion associated with an architecture and driver
558 ****************************************************************************/
559 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
560 struct current_user *user, uint32 *perr)
566 char buf[PE_HEADER_SIZE];
571 files_struct *fsp = NULL;
575 connection_struct *conn;
579 /* If architecture is Windows 95/98, the version is always 0. */
580 if (strcmp(architecture, "WIN40") == 0) {
581 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
586 pass = sys_getpwuid(user->uid);
588 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
589 (unsigned int)user->uid ));
591 *perr = ERROR_ACCESS_DENIED;
596 /* connect to the print$ share under the same account as the user connected
598 fstrcpy(user_name, pass->pw_name );
599 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
601 /* Null password is ok - we are already an authenticated user... */
603 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
606 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
607 *perr = (uint32)ecode;
611 /* Save who we are - we are temporarily becoming the connection user. */
614 if (!become_user(conn, conn->vuid)) {
615 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
616 *perr = ERROR_ACCESS_DENIED;
621 /* Open the driver file (Portable Executable format) and determine the
622 * deriver the cversion. */
623 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
625 unix_convert(driverpath,conn,NULL,&bad_path,&st);
627 fsp = open_file_shared(conn, driverpath, &st,
628 SET_OPEN_MODE(DOS_OPEN_RDONLY),
629 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
630 0, 0, &access_mode, &action);
632 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
634 *perr = ERROR_ACCESS_DENIED;
638 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
639 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
640 driverpath, byte_count));
641 *perr = NT_STATUS_FILE_INVALID;
645 /* Is this really a DOS header? */
646 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
647 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
648 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
649 *perr = NT_STATUS_FILE_INVALID;
653 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
654 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
655 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
657 *perr = NT_STATUS_FILE_INVALID;
661 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
662 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
663 driverpath, byte_count));
664 *perr = NT_STATUS_FILE_INVALID;
668 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
669 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
670 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
672 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
673 case 4: cversion = 2; break; /* Win NT 4 */
674 case 5: cversion = 3; break; /* Win 2000 */
676 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
677 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
678 *perr = NT_STATUS_FILE_INVALID;
682 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
683 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
684 *perr = NT_STATUS_FILE_INVALID;
688 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
689 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
691 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
692 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
693 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
695 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
696 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
697 *perr = NT_STATUS_FILE_INVALID;
701 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
702 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
703 *perr = NT_STATUS_FILE_INVALID;
708 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
709 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
710 *perr = NT_STATUS_FILE_INVALID;
714 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
715 driverpath, cversion));
717 close_file(fsp, True);
718 close_cnum(conn, user->vuid);
725 close_file(fsp, True);
727 close_cnum(conn, user->vuid);
732 /****************************************************************************
733 ****************************************************************************/
734 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
735 struct current_user *user)
737 fstring architecture;
743 /* clean up the driver name.
744 * we can get .\driver.dll
745 * or worse c:\windows\system\driver.dll !
747 /* using an intermediate string to not have overlaping memcpy()'s */
748 if ((p = strrchr_m(driver->driverpath,'\\')) != NULL) {
749 fstrcpy(new_name, p+1);
750 fstrcpy(driver->driverpath, new_name);
753 if ((p = strrchr_m(driver->datafile,'\\')) != NULL) {
754 fstrcpy(new_name, p+1);
755 fstrcpy(driver->datafile, new_name);
758 if ((p = strrchr_m(driver->configfile,'\\')) != NULL) {
759 fstrcpy(new_name, p+1);
760 fstrcpy(driver->configfile, new_name);
763 if ((p = strrchr_m(driver->helpfile,'\\')) != NULL) {
764 fstrcpy(new_name, p+1);
765 fstrcpy(driver->helpfile, new_name);
768 if (driver->dependentfiles) {
769 for (i=0; *driver->dependentfiles[i]; i++) {
770 if ((p = strrchr_m(driver->dependentfiles[i],'\\')) != NULL) {
771 fstrcpy(new_name, p+1);
772 fstrcpy(driver->dependentfiles[i], new_name);
777 get_short_archi(architecture, driver->environment);
779 /* jfm:7/16/2000 the client always sends the cversion=0.
780 * The server should check which version the driver is by reading
781 * the PE header of driver->driverpath.
783 * For Windows 95/98 the version is 0 (so the value sent is correct)
784 * For Windows NT (the architecture doesn't matter)
786 * NT 3.5/3.51: cversion=1
790 if ((driver->cversion = get_correct_cversion( architecture,
791 driver->driverpath, user, &err)) == -1)
794 return NT_STATUS_NOPROBLEMO;
797 /****************************************************************************
798 ****************************************************************************/
799 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
800 struct current_user *user)
802 fstring architecture;
808 /* clean up the driver name.
809 * we can get .\driver.dll
810 * or worse c:\windows\system\driver.dll !
812 /* using an intermediate string to not have overlaping memcpy()'s */
813 if ((p = strrchr_m(driver->driverpath,'\\')) != NULL) {
814 fstrcpy(new_name, p+1);
815 fstrcpy(driver->driverpath, new_name);
818 if ((p = strrchr_m(driver->datafile,'\\')) != NULL) {
819 fstrcpy(new_name, p+1);
820 fstrcpy(driver->datafile, new_name);
823 if ((p = strrchr_m(driver->configfile,'\\')) != NULL) {
824 fstrcpy(new_name, p+1);
825 fstrcpy(driver->configfile, new_name);
828 if ((p = strrchr_m(driver->helpfile,'\\')) != NULL) {
829 fstrcpy(new_name, p+1);
830 fstrcpy(driver->helpfile, new_name);
833 if (driver->dependentfiles) {
834 for (i=0; *driver->dependentfiles[i]; i++) {
835 if ((p = strrchr_m(driver->dependentfiles[i],'\\')) != NULL) {
836 fstrcpy(new_name, p+1);
837 fstrcpy(driver->dependentfiles[i], new_name);
842 get_short_archi(architecture, driver->environment);
844 /* jfm:7/16/2000 the client always sends the cversion=0.
845 * The server should check which version the driver is by reading
846 * the PE header of driver->driverpath.
848 * For Windows 95/98 the version is 0 (so the value sent is correct)
849 * For Windows NT (the architecture doesn't matter)
851 * NT 3.5/3.51: cversion=1
855 if ((driver->version = get_correct_cversion(architecture,
856 driver->driverpath, user, &err)) == -1)
859 return NT_STATUS_NOPROBLEMO;
862 /****************************************************************************
863 ****************************************************************************/
864 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
865 uint32 level, struct current_user *user)
870 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
871 driver=driver_abstract.info_3;
872 return clean_up_driver_struct_level_3(driver, user);
876 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
877 driver=driver_abstract.info_6;
878 return clean_up_driver_struct_level_6(driver, user);
881 return ERROR_INVALID_PARAMETER;
885 /****************************************************************************
886 This function sucks and should be replaced. JRA.
887 ****************************************************************************/
889 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
891 dst->cversion = src->version;
893 fstrcpy( dst->name, src->name);
894 fstrcpy( dst->environment, src->environment);
895 fstrcpy( dst->driverpath, src->driverpath);
896 fstrcpy( dst->datafile, src->datafile);
897 fstrcpy( dst->configfile, src->configfile);
898 fstrcpy( dst->helpfile, src->helpfile);
899 fstrcpy( dst->monitorname, src->monitorname);
900 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
901 dst->dependentfiles = src->dependentfiles;
904 #if 0 /* Debugging function */
906 static char* ffmt(unsigned char *c){
908 static char ffmt_str[17];
910 for (i=0; i<16; i++) {
911 if ((c[i] < ' ') || (c[i] > '~'))
922 /****************************************************************************
923 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
924 There are two case to be covered here: PE (Portable Executable) and NE (New
925 Executable) files. Both files support the same INFO structure, but PE files
926 store the signature in unicode, and NE files store it as !unicode.
927 ****************************************************************************/
928 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
935 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
936 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
937 fname, PE_HEADER_SIZE));
941 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
942 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
943 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
945 goto no_version_info;
948 /* Is this really a DOS header? */
949 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
950 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
951 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
952 goto no_version_info;
955 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
956 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
957 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
959 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
960 goto no_version_info;
963 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
964 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
966 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
967 goto no_version_info;
970 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
971 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
973 int section_table_bytes;
975 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
976 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
977 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
978 /* At this point, we assume the file is in error. It still could be somthing
979 * else besides a PE file, but it unlikely at this point.
984 /* get the section table */
985 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
986 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
988 if ((buf=malloc(section_table_bytes)) == NULL) {
989 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
990 fname, section_table_bytes));
994 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
995 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
1000 /* Iterate the section table looking for the resource section ".rsrc" */
1001 for (i = 0; i < num_sections; i++) {
1002 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1004 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1005 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1006 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1009 if ((buf=malloc(section_bytes)) == NULL) {
1010 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1011 fname, section_bytes));
1015 /* Seek to the start of the .rsrc section info */
1016 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1017 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1022 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1023 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
1024 fname, byte_count));
1028 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1029 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1030 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1031 /* Align to next long address */
1032 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1034 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1035 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1036 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1038 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1039 fname, *major, *minor,
1040 (*major>>16)&0xffff, *major&0xffff,
1041 (*minor>>16)&0xffff, *minor&0xffff));
1050 /* Version info not found, fall back to origin date/time */
1051 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1055 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1056 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1057 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1058 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1059 /* At this point, we assume the file is in error. It still could be somthing
1060 * else besides a NE file, but it unlikely at this point. */
1064 /* Allocate a bit more space to speed up things */
1066 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
1067 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1068 fname, PE_HEADER_SIZE));
1072 /* This is a HACK! I got tired of trying to sort through the messy
1073 * 'NE' file format. If anyone wants to clean this up please have at
1074 * it, but this works. 'NE' files will eventually fade away. JRR */
1075 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1076 /* Cover case that should not occur in a well formed 'NE' .dll file */
1077 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1079 for(i=0; i<byte_count; i++) {
1080 /* Fast skip past data that can't possibly match */
1081 if (buf[i] != 'V') continue;
1083 /* Potential match data crosses buf boundry, move it to beginning
1084 * of buf, and fill the buf with as much as it will hold. */
1085 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1088 memcpy(buf, &buf[i], byte_count-i);
1089 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1090 (byte_count-i))) < 0) {
1092 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1097 byte_count = bc + (byte_count - i);
1098 if (byte_count<VS_VERSION_INFO_SIZE) break;
1103 /* Check that the full signature string and the magic number that
1104 * follows exist (not a perfect solution, but the chances that this
1105 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1106 * twice, as it is simpler to read the code. */
1107 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1108 /* Compute skip alignment to next long address */
1109 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1110 sizeof(VS_SIGNATURE)) & 3;
1111 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1113 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1114 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1115 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1116 fname, *major, *minor,
1117 (*major>>16)&0xffff, *major&0xffff,
1118 (*minor>>16)&0xffff, *minor&0xffff));
1125 /* Version info not found, fall back to origin date/time */
1126 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1131 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1132 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1133 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1144 /****************************************************************************
1145 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1146 share one or more files. During the MS installation process files are checked
1147 to insure that only a newer version of a shared file is installed over an
1148 older version. There are several possibilities for this comparison. If there
1149 is no previous version, the new one is newer (obviously). If either file is
1150 missing the version info structure, compare the creation date (on Unix use
1151 the modification date). Otherwise chose the numerically larger version number.
1152 ****************************************************************************/
1153 static int file_version_is_newer(connection_struct *conn, fstring new_file,
1156 BOOL use_version = True;
1161 time_t new_create_time;
1165 time_t old_create_time;
1169 files_struct *fsp = NULL;
1171 SMB_STRUCT_STAT stat_buf;
1175 ZERO_STRUCT(stat_buf);
1176 new_create_time = (time_t)0;
1177 old_create_time = (time_t)0;
1179 /* Get file version info (if available) for previous file (if it exists) */
1180 pstrcpy(filepath, old_file);
1182 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1184 fsp = open_file_shared(conn, filepath, &stat_buf,
1185 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1186 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1187 0, 0, &access_mode, &action);
1189 /* Old file not found, so by definition new file is in fact newer */
1190 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1195 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1196 if (ret == -1) goto error_exit;
1199 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1201 use_version = False;
1202 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1203 old_create_time = st.st_mtime;
1204 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1207 close_file(fsp, True);
1209 /* Get file version info (if available) for new file */
1210 pstrcpy(filepath, new_file);
1211 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1213 fsp = open_file_shared(conn, filepath, &stat_buf,
1214 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1215 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1216 0, 0, &access_mode, &action);
1218 /* New file not found, this shouldn't occur if the caller did its job */
1219 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1224 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1225 if (ret == -1) goto error_exit;
1228 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1230 use_version = False;
1231 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1232 new_create_time = st.st_mtime;
1233 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1236 close_file(fsp, True);
1239 /* Compare versions and choose the larger version number */
1240 if (new_major > old_major ||
1241 (new_major == old_major && new_minor > old_minor)) {
1243 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1247 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1252 /* Compare modification time/dates and choose the newest time/date */
1253 if (new_create_time > old_create_time) {
1254 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1258 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1265 close_file(fsp, True);
1269 /****************************************************************************
1270 ****************************************************************************/
1271 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1273 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1274 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1275 fstring architecture;
1281 connection_struct *conn;
1284 struct passwd *pass;
1290 memset(inbuf, '\0', sizeof(inbuf));
1291 memset(outbuf, '\0', sizeof(outbuf));
1294 driver=driver_abstract.info_3;
1295 else if (level==6) {
1296 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1297 driver = &converted_driver;
1299 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1303 get_short_archi(architecture, driver->environment);
1306 pass = sys_getpwuid(user->uid);
1308 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1309 (unsigned int)user->uid ));
1315 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1316 fstrcpy(user_name, pass->pw_name );
1317 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1319 /* Null password is ok - we are already an authenticated user... */
1321 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1324 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1325 *perr = (uint32)ecode;
1330 * Save who we are - we are temporarily becoming the connection user.
1335 if (!become_user(conn, conn->vuid)) {
1336 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1342 * make the directories version and version\driver_name
1343 * under the architecture directory.
1345 DEBUG(5,("Creating first directory\n"));
1346 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1347 mkdir_internal(conn, inbuf, outbuf, new_dir);
1349 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1350 * listed for this driver which has already been moved, skip it (note:
1351 * drivers may list the same file name several times. Then check if the
1352 * file already exists in archi\cversion\, if so, check that the version
1353 * info (or time stamps if version info is unavailable) is newer (or the
1354 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1355 * Otherwise, delete the file.
1357 * If a file is not moved to archi\cversion\ because of an error, all the
1358 * rest of the 'unmoved' driver files are removed from archi\. If one or
1359 * more of the driver's files was already moved to archi\cversion\, it
1360 * potentially leaves the driver in a partially updated state. Version
1361 * trauma will most likely occur if an client attempts to use any printer
1362 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1363 * done is appropriate... later JRR
1366 DEBUG(5,("Moving files now !\n"));
1368 if (driver->driverpath && strlen(driver->driverpath)) {
1369 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1370 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1371 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1372 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1373 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1374 new_name, old_name));
1375 *perr = (uint32)SVAL(outbuf,smb_err);
1376 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1381 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1384 if (driver->datafile && strlen(driver->datafile)) {
1385 if (!strequal(driver->datafile, driver->driverpath)) {
1386 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1387 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1388 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1389 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1390 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1391 new_name, old_name));
1392 *perr = (uint32)SVAL(outbuf,smb_err);
1393 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1398 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1402 if (driver->configfile && strlen(driver->configfile)) {
1403 if (!strequal(driver->configfile, driver->driverpath) &&
1404 !strequal(driver->configfile, driver->datafile)) {
1405 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1406 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1407 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1408 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1409 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1410 new_name, old_name));
1411 *perr = (uint32)SVAL(outbuf,smb_err);
1412 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1417 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1421 if (driver->helpfile && strlen(driver->helpfile)) {
1422 if (!strequal(driver->helpfile, driver->driverpath) &&
1423 !strequal(driver->helpfile, driver->datafile) &&
1424 !strequal(driver->helpfile, driver->configfile)) {
1425 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1426 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1427 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1428 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1429 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1430 new_name, old_name));
1431 *perr = (uint32)SVAL(outbuf,smb_err);
1432 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1437 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1441 if (driver->dependentfiles) {
1442 for (i=0; *driver->dependentfiles[i]; i++) {
1443 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1444 !strequal(driver->dependentfiles[i], driver->datafile) &&
1445 !strequal(driver->dependentfiles[i], driver->configfile) &&
1446 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1448 for (j=0; j < i; j++) {
1449 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1454 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1455 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1456 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1457 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1458 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1459 new_name, old_name));
1460 *perr = (uint32)SVAL(outbuf,smb_err);
1461 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1466 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1472 close_cnum(conn, user->vuid);
1475 return ver == -1 ? False : True;
1478 /****************************************************************************
1479 ****************************************************************************/
1480 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1483 fstring architecture;
1489 TDB_DATA kbuf, dbuf;
1491 get_short_archi(architecture, driver->environment);
1493 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1494 * \\server is added in the rpc server layer.
1495 * It does make sense to NOT store the server's name in the printer TDB.
1498 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1500 /* .inf files do not always list a file for each of the four standard files.
1501 * Don't prepend a path to a null filename, or client claims:
1502 * "The server on which the printer resides does not have a suitable
1503 * <printer driver name> printer driver installed. Click OK if you
1504 * wish to install the driver on your local machine."
1506 if (strlen(driver->driverpath)) {
1507 fstrcpy(temp_name, driver->driverpath);
1508 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1511 if (strlen(driver->datafile)) {
1512 fstrcpy(temp_name, driver->datafile);
1513 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1516 if (strlen(driver->configfile)) {
1517 fstrcpy(temp_name, driver->configfile);
1518 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1521 if (strlen(driver->helpfile)) {
1522 fstrcpy(temp_name, driver->helpfile);
1523 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1526 if (driver->dependentfiles) {
1527 for (i=0; *driver->dependentfiles[i]; i++) {
1528 fstrcpy(temp_name, driver->dependentfiles[i]);
1529 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1533 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1535 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1542 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1545 driver->environment,
1550 driver->monitorname,
1551 driver->defaultdatatype);
1553 if (driver->dependentfiles) {
1554 for (i=0; *driver->dependentfiles[i]; i++) {
1555 len += tdb_pack(buf+len, buflen-len, "f",
1556 driver->dependentfiles[i]);
1560 if (len != buflen) {
1561 buf = (char *)Realloc(buf, len);
1568 kbuf.dsize = strlen(key)+1;
1572 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1575 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1581 /****************************************************************************
1582 ****************************************************************************/
1583 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1585 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1588 info3.cversion = driver->version;
1589 fstrcpy(info3.name,driver->name);
1590 fstrcpy(info3.environment,driver->environment);
1591 fstrcpy(info3.driverpath,driver->driverpath);
1592 fstrcpy(info3.datafile,driver->datafile);
1593 fstrcpy(info3.configfile,driver->configfile);
1594 fstrcpy(info3.helpfile,driver->helpfile);
1595 fstrcpy(info3.monitorname,driver->monitorname);
1596 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1597 info3.dependentfiles = driver->dependentfiles;
1599 return add_a_printer_driver_3(&info3);
1603 /****************************************************************************
1604 ****************************************************************************/
1605 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1607 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1611 fstrcpy(info.name, in_prt);
1612 fstrcpy(info.defaultdatatype, "RAW");
1614 fstrcpy(info.driverpath, "");
1615 fstrcpy(info.datafile, "");
1616 fstrcpy(info.configfile, "");
1617 fstrcpy(info.helpfile, "");
1619 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1620 return ERROR_NOT_ENOUGH_MEMORY;
1622 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1623 fstrcpy(info.dependentfiles[0], "");
1625 *info_ptr = memdup(&info, sizeof(info));
1630 /****************************************************************************
1631 ****************************************************************************/
1632 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1634 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1635 TDB_DATA kbuf, dbuf;
1636 fstring architecture;
1641 ZERO_STRUCT(driver);
1643 get_short_archi(architecture, in_arch);
1645 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1647 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1650 kbuf.dsize = strlen(key)+1;
1652 dbuf = tdb_fetch(tdb_drivers, kbuf);
1654 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1656 if (!dbuf.dptr) return 5;
1658 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1667 driver.defaultdatatype);
1670 while (len < dbuf.dsize) {
1671 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1672 sizeof(fstring)*(i+2));
1673 if (driver.dependentfiles == NULL)
1676 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1677 &driver.dependentfiles[i]);
1680 if (driver.dependentfiles != NULL)
1681 fstrcpy(driver.dependentfiles[i], "");
1683 safe_free(dbuf.dptr);
1685 if (len != dbuf.dsize) {
1686 if (driver.dependentfiles != NULL)
1687 safe_free(driver.dependentfiles);
1689 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1692 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1697 /****************************************************************************
1698 ****************************************************************************/
1699 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1701 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1707 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1708 DEBUG(10,("driver key: [%s]\n", key));
1711 kbuf.dsize = strlen(key)+1;
1712 if (!tdb_exists(tdb_drivers, kbuf)) return False;
1715 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1717 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1718 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1719 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1720 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1721 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1722 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1723 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1725 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1726 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1727 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1729 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1730 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1731 pstrcat(line, info3->configfile);
1733 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1734 pstrcat(line, info3->datafile);
1736 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1737 pstrcat(line, info3->helpfile);
1739 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1740 pstrcat(line, info3->monitorname);
1742 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1745 for (i=0; info3->dependentfiles &&
1746 *info3->dependentfiles[i]; i++) {
1747 if (i) pstrcat(line, ","); /* don't end in a "," */
1748 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1749 pstrcat(line, info3->dependentfiles[i]);
1757 /****************************************************************************
1758 debugging function, dump at level 6 the struct in the logs
1759 ****************************************************************************/
1760 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1763 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1766 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1772 if (driver.info_3 == NULL)
1775 info3=driver.info_3;
1777 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1778 DEBUGADD(106,("name:[%s]\n", info3->name));
1779 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1780 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1781 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1782 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1783 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1784 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1785 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1787 for (i=0; info3->dependentfiles &&
1788 *info3->dependentfiles[i]; i++) {
1789 DEBUGADD(106,("dependentfile:[%s]\n",
1790 info3->dependentfiles[i]));
1797 DEBUGADD(1,("Level not implemented\n"));
1805 /****************************************************************************
1806 ****************************************************************************/
1807 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1811 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1813 if (!nt_devmode) return len;
1815 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1816 nt_devmode->devicename,
1817 nt_devmode->formname,
1819 nt_devmode->specversion,
1820 nt_devmode->driverversion,
1822 nt_devmode->driverextra,
1823 nt_devmode->orientation,
1824 nt_devmode->papersize,
1825 nt_devmode->paperlength,
1826 nt_devmode->paperwidth,
1829 nt_devmode->defaultsource,
1830 nt_devmode->printquality,
1833 nt_devmode->yresolution,
1834 nt_devmode->ttoption,
1835 nt_devmode->collate,
1836 nt_devmode->logpixels,
1839 nt_devmode->bitsperpel,
1840 nt_devmode->pelswidth,
1841 nt_devmode->pelsheight,
1842 nt_devmode->displayflags,
1843 nt_devmode->displayfrequency,
1844 nt_devmode->icmmethod,
1845 nt_devmode->icmintent,
1846 nt_devmode->mediatype,
1847 nt_devmode->dithertype,
1848 nt_devmode->reserved1,
1849 nt_devmode->reserved2,
1850 nt_devmode->panningwidth,
1851 nt_devmode->panningheight,
1852 nt_devmode->private);
1855 if (nt_devmode->private) {
1856 len += tdb_pack(buf+len, buflen-len, "B",
1857 nt_devmode->driverextra,
1858 nt_devmode->private);
1861 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1866 /****************************************************************************
1867 ****************************************************************************/
1868 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1872 while (param != NULL) {
1873 len += tdb_pack(buf+len, buflen-len, "pfdB",
1882 len += tdb_pack(buf+len, buflen-len, "p", param);
1888 /****************************************************************************
1889 delete a printer - this just deletes the printer info file, any open
1890 handles are not affected
1891 ****************************************************************************/
1892 uint32 del_a_printer(char *sharename)
1897 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1900 kbuf.dsize=strlen(key)+1;
1902 tdb_delete(tdb_printers, kbuf);
1906 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1907 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1908 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1909 /****************************************************************************
1910 ****************************************************************************/
1911 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1915 int buflen, len, ret;
1916 TDB_DATA kbuf, dbuf;
1919 * in addprinter: no servername and the printer is the name
1920 * in setprinter: servername is \\server
1921 * and printer is \\server\\printer
1923 * Samba manages only local printers.
1924 * we currently don't support things like path=\\other_server\printer
1927 if (info->servername[0]!='\0') {
1928 trim_string(info->printername, info->servername, NULL);
1929 trim_string(info->printername, "\\", NULL);
1930 info->servername[0]='\0';
1934 * JFM: one day I'll forget.
1935 * below that's info->portname because that's the SAMBA sharename
1936 * and I made NT 'thinks' it's the portname
1937 * the info->sharename is the thing you can name when you add a printer
1938 * that's the short-name when you create shared printer for 95/98
1939 * So I've made a limitation in SAMBA: you can only have 1 printer model
1940 * behind a SAMBA share.
1948 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1951 info->default_priority,
1968 info->printprocessor,
1972 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1974 len += pack_specifics(info->specific, buf+len, buflen-len);
1976 if (buflen != len) {
1977 buf = (char *)Realloc(buf, len);
1983 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1986 kbuf.dsize = strlen(key)+1;
1990 ret = tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
1993 DEBUG(8, ("error updating printer to tdb on disk\n"));
1997 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1998 info->sharename, info->drivername, info->portname, len));
2004 /****************************************************************************
2005 ****************************************************************************/
2006 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
2008 NT_PRINTER_PARAM *current;
2010 DEBUG(108,("add_a_specific_param\n"));
2012 (*param)->next=NULL;
2014 if (info_2->specific == NULL)
2016 info_2->specific=*param;
2020 current=info_2->specific;
2021 while (current->next != NULL) {
2022 current=current->next;
2024 current->next=*param;
2030 /****************************************************************************
2031 ****************************************************************************/
2032 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2034 NT_PRINTER_PARAM *current;
2035 NT_PRINTER_PARAM *previous;
2037 current=info_2->specific;
2040 if (current==NULL) return (False);
2042 if ( !strcmp(current->value, param->value) &&
2043 (strlen(current->value)==strlen(param->value)) ) {
2044 DEBUG(109,("deleting first value\n"));
2045 info_2->specific=current->next;
2046 safe_free(current->data);
2048 DEBUG(109,("deleted first value\n"));
2052 current=previous->next;
2054 while ( current!=NULL ) {
2055 if (!strcmp(current->value, param->value) &&
2056 strlen(current->value)==strlen(param->value) ) {
2057 DEBUG(109,("deleting current value\n"));
2058 previous->next=current->next;
2059 safe_free(current->data);
2061 DEBUG(109,("deleted current value\n"));
2065 previous=previous->next;
2066 current=current->next;
2071 /****************************************************************************
2072 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2073 ****************************************************************************/
2074 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2076 NT_PRINTER_PARAM *param = *param_ptr;
2081 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2084 safe_free(param->data);
2090 /****************************************************************************
2091 Malloc and return an NT devicemode.
2092 ****************************************************************************/
2094 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2097 * should I init this ones ???
2098 nt_devmode->devicename
2102 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2104 if (nt_devmode == NULL) {
2105 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2109 ZERO_STRUCTP(nt_devmode);
2111 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2112 fstrcpy(nt_devmode->devicename, adevice);
2114 fstrcpy(nt_devmode->formname, "Letter");
2116 nt_devmode->specversion = 0x0401;
2117 nt_devmode->driverversion = 0x0400;
2118 nt_devmode->size = 0x00DC;
2119 nt_devmode->driverextra = 0x0000;
2120 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2121 DEFAULTSOURCE | COPIES | SCALE |
2122 PAPERSIZE | ORIENTATION;
2123 nt_devmode->orientation = 1;
2124 nt_devmode->papersize = PAPER_LETTER;
2125 nt_devmode->paperlength = 0;
2126 nt_devmode->paperwidth = 0;
2127 nt_devmode->scale = 0x64;
2128 nt_devmode->copies = 01;
2129 nt_devmode->defaultsource = BIN_FORMSOURCE;
2130 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2131 nt_devmode->color = COLOR_MONOCHROME;
2132 nt_devmode->duplex = DUP_SIMPLEX;
2133 nt_devmode->yresolution = 0;
2134 nt_devmode->ttoption = TT_SUBDEV;
2135 nt_devmode->collate = COLLATE_FALSE;
2136 nt_devmode->icmmethod = 0;
2137 nt_devmode->icmintent = 0;
2138 nt_devmode->mediatype = 0;
2139 nt_devmode->dithertype = 0;
2141 /* non utilisés par un driver d'imprimante */
2142 nt_devmode->logpixels = 0;
2143 nt_devmode->bitsperpel = 0;
2144 nt_devmode->pelswidth = 0;
2145 nt_devmode->pelsheight = 0;
2146 nt_devmode->displayflags = 0;
2147 nt_devmode->displayfrequency = 0;
2148 nt_devmode->reserved1 = 0;
2149 nt_devmode->reserved2 = 0;
2150 nt_devmode->panningwidth = 0;
2151 nt_devmode->panningheight = 0;
2153 nt_devmode->private = NULL;
2157 /****************************************************************************
2158 Deepcopy an NT devicemode.
2159 ****************************************************************************/
2161 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2163 NT_DEVICEMODE *new_nt_devicemode = NULL;
2165 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2166 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2170 new_nt_devicemode->private = NULL;
2171 if (nt_devicemode->private != NULL) {
2172 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2173 safe_free(new_nt_devicemode);
2174 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2179 return new_nt_devicemode;
2182 /****************************************************************************
2183 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2184 ****************************************************************************/
2186 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2188 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2190 if(nt_devmode == NULL)
2193 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2195 if(nt_devmode->private)
2196 safe_free(nt_devmode->private);
2198 safe_free(nt_devmode);
2199 *devmode_ptr = NULL;
2202 /****************************************************************************
2203 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2204 ****************************************************************************/
2205 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2207 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2208 NT_PRINTER_PARAM *param_ptr;
2213 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2215 free_nt_devicemode(&info->devmode);
2217 for(param_ptr = info->specific; param_ptr; ) {
2218 NT_PRINTER_PARAM *tofree = param_ptr;
2220 param_ptr = param_ptr->next;
2221 free_nt_printer_param(&tofree);
2224 safe_free(*info_ptr);
2229 /****************************************************************************
2230 ****************************************************************************/
2231 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2235 NT_DEVICEMODE devmode;
2237 ZERO_STRUCT(devmode);
2239 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2241 if (!*nt_devmode) return len;
2243 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2247 &devmode.specversion,
2248 &devmode.driverversion,
2250 &devmode.driverextra,
2251 &devmode.orientation,
2253 &devmode.paperlength,
2254 &devmode.paperwidth,
2257 &devmode.defaultsource,
2258 &devmode.printquality,
2261 &devmode.yresolution,
2267 &devmode.bitsperpel,
2269 &devmode.pelsheight,
2270 &devmode.displayflags,
2271 &devmode.displayfrequency,
2275 &devmode.dithertype,
2278 &devmode.panningwidth,
2279 &devmode.panningheight,
2282 if (devmode.private) {
2283 /* the len in tdb_unpack is an int value and
2284 * devmode.driverextra is only a short
2286 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2287 devmode.driverextra=(uint16)extra_len;
2289 /* check to catch an invalid TDB entry so we don't segfault */
2290 if (devmode.driverextra == 0) {
2291 devmode.private = NULL;
2295 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2297 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2298 if (devmode.private)
2299 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2304 /****************************************************************************
2305 ****************************************************************************/
2306 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2309 NT_PRINTER_PARAM param, *p;
2314 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2317 len += tdb_unpack(buf+len, buflen-len, "fdB",
2323 *list = memdup(¶m, sizeof(param));
2325 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2331 static void map_to_os2_driver(fstring drivername)
2333 static BOOL initialised=False;
2334 static fstring last_from,last_to;
2335 char *mapfile = lp_os2_driver_map();
2336 char **lines = NULL;
2340 if (!strlen(drivername))
2347 *last_from = *last_to = 0;
2351 if (strequal(drivername,last_from)) {
2352 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2353 fstrcpy(drivername,last_to);
2357 lines = file_lines_load(mapfile, &numlines);
2358 if (numlines == 0) {
2359 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2363 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2365 for( i = 0; i < numlines; i++) {
2366 char *nt_name = lines[i];
2367 char *os2_name = strchr_m(nt_name,'=');
2374 while (isspace(*nt_name))
2377 if (!*nt_name || strchr_m("#;",*nt_name))
2381 int l = strlen(nt_name);
2382 while (l && isspace(nt_name[l-1])) {
2388 while (isspace(*os2_name))
2392 int l = strlen(os2_name);
2393 while (l && isspace(os2_name[l-1])) {
2399 if (strequal(nt_name,drivername)) {
2400 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2401 fstrcpy(last_from,drivername);
2402 fstrcpy(last_to,os2_name);
2403 fstrcpy(drivername,os2_name);
2404 file_lines_free(lines);
2409 file_lines_free(lines);
2412 /****************************************************************************
2413 get a default printer info 2 struct
2414 ****************************************************************************/
2415 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2417 extern pstring global_myname;
2419 NT_PRINTER_INFO_LEVEL_2 info;
2423 snum = lp_servicenumber(sharename);
2425 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2426 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2427 global_myname, sharename);
2428 fstrcpy(info.sharename, sharename);
2429 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2430 fstrcpy(info.drivername, lp_printerdriver(snum));
2433 if (!*info.drivername)
2434 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2436 /* by setting the driver name to an empty string, a local NT admin
2437 can now run the **local** APW to install a local printer driver
2438 for a Samba shared printer in 2.2. Without this, drivers **must** be
2439 installed on the Samba server for NT clients --jerry */
2440 if (!*info.drivername)
2441 fstrcpy(info.drivername, "");
2445 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2447 pstrcpy(info.comment, "");
2448 fstrcpy(info.printprocessor, "winprint");
2449 fstrcpy(info.datatype, "RAW");
2451 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2452 | PRINTER_ATTRIBUTE_LOCAL \
2453 | PRINTER_ATTRIBUTE_RAW_ONLY \
2454 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2456 info.starttime = 0; /* Minutes since 12:00am GMT */
2457 info.untiltime = 0; /* Minutes since 12:00am GMT */
2459 info.default_priority = 1;
2460 info.setuptime = (uint32)time(NULL);
2462 #if 1 /* JRA - NO NOT CHANGE ! */
2463 info.devmode = NULL;
2466 * We should not return a default devicemode, as this causes
2467 * Win2K to not send the correct one on PCL drivers. It needs to
2468 * see a null devicemode so it can then overwrite the devicemode
2469 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2471 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2475 /* This will get the current RPC talloc context, but we should be
2476 passing this as a parameter... fixme... JRA ! */
2478 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2481 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2483 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2492 free_nt_devicemode(&info.devmode);
2496 /****************************************************************************
2497 ****************************************************************************/
2498 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2501 NT_PRINTER_INFO_LEVEL_2 info;
2503 TDB_DATA kbuf, dbuf;
2504 fstring printername;
2508 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2511 kbuf.dsize = strlen(key)+1;
2513 dbuf = tdb_fetch(tdb_printers, kbuf);
2515 return get_a_printer_2_default(info_ptr, sharename);
2517 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2520 &info.default_priority,
2537 info.printprocessor,
2541 /* Samba has to have shared raw drivers. */
2542 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2544 /* Restore the stripped strings. */
2545 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2546 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2548 fstrcpy(info.printername, printername);
2550 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2551 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2553 /* This will get the current RPC talloc context, but we should be
2554 passing this as a parameter... fixme... JRA ! */
2556 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2558 /* Fix for OS/2 drivers. */
2560 if (get_remote_arch() == RA_OS2)
2561 map_to_os2_driver(info.drivername);
2563 safe_free(dbuf.dptr);
2564 *info_ptr=memdup(&info, sizeof(info));
2566 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2567 sharename, info.printername, info.drivername));
2573 /****************************************************************************
2574 debugging function, dump at level 6 the struct in the logs
2575 ****************************************************************************/
2576 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2579 NT_PRINTER_INFO_LEVEL_2 *info2;
2581 DEBUG(106,("Dumping printer at level [%d]\n", level));
2587 if (printer.info_2 == NULL)
2591 info2=printer.info_2;
2593 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2594 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2595 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2596 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2597 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2598 DEBUGADD(106,("status:[%d]\n", info2->status));
2599 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2600 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2601 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2602 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2603 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2605 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2606 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2607 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2608 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2609 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2610 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2611 DEBUGADD(106,("location:[%s]\n", info2->location));
2612 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2613 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2614 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2615 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2621 DEBUGADD(1,("Level not implemented\n"));
2629 /****************************************************************************
2630 Get the parameters we can substitute in an NT print job.
2631 ****************************************************************************/
2633 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2635 NT_PRINTER_INFO_LEVEL *printer = NULL;
2637 **printername = **sharename = **portname = '\0';
2639 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2642 fstrcpy(*printername, printer->info_2->printername);
2643 fstrcpy(*sharename, printer->info_2->sharename);
2644 fstrcpy(*portname, printer->info_2->portname);
2646 free_a_printer(&printer, 2);
2650 * The function below are the high level ones.
2651 * only those ones must be called from the spoolss code.
2655 /****************************************************************************
2656 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2657 ****************************************************************************/
2659 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2663 dump_a_printer(printer, level);
2669 printer.info_2->c_setprinter++;
2670 result=update_a_printer_2(printer.info_2);
2681 /****************************************************************************
2682 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2683 We split this out from mod_a_printer as it updates the id's and timestamps.
2684 ****************************************************************************/
2686 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2690 dump_a_printer(printer, level);
2697 * Update the changestamp.
2698 * Note we must *not* do this in mod_a_printer().
2701 time_t time_unix = time(NULL);
2702 unix_to_nt_time(&time_nt, time_unix);
2703 if (printer.info_2->changeid==time_nt.low)
2704 printer.info_2->changeid++;
2706 printer.info_2->changeid=time_nt.low;
2708 printer.info_2->c_setprinter++;
2710 result=update_a_printer_2(printer.info_2);
2721 /****************************************************************************
2722 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2723 ****************************************************************************/
2725 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2728 NT_PRINTER_INFO_LEVEL *printer = NULL;
2732 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2738 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2739 DEBUG(0,("get_a_printer: malloc fail.\n"));
2742 ZERO_STRUCTP(printer);
2743 result=get_a_printer_2(&printer->info_2, sharename);
2745 dump_a_printer(*printer, level);
2746 *pp_printer = printer;
2757 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2762 /****************************************************************************
2763 Deletes a NT_PRINTER_INFO_LEVEL struct.
2764 ****************************************************************************/
2766 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2769 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2771 DEBUG(104,("freeing a printer at level [%d]\n", level));
2773 if (printer == NULL)
2780 if (printer->info_2 != NULL)
2782 free_nt_printer_info_level_2(&printer->info_2);
2801 /****************************************************************************
2802 ****************************************************************************/
2803 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2806 DEBUG(104,("adding a printer at level [%d]\n", level));
2807 dump_a_printer_driver(driver, level);
2813 result=add_a_printer_driver_3(driver.info_3);
2819 result=add_a_printer_driver_6(driver.info_6);
2829 /****************************************************************************
2830 ****************************************************************************/
2831 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2832 fstring printername, fstring architecture, uint32 version)
2840 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2849 dump_a_printer_driver(*driver, level);
2853 /****************************************************************************
2854 ****************************************************************************/
2855 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2863 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2864 if (driver.info_3 != NULL)
2866 info3=driver.info_3;
2867 safe_free(info3->dependentfiles);
2868 ZERO_STRUCTP(info3);
2880 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2881 if (driver.info_6 != NULL)
2883 info6=driver.info_6;
2884 safe_free(info6->dependentfiles);
2885 safe_free(info6->previousnames);
2886 ZERO_STRUCTP(info6);
2904 /****************************************************************************
2905 Determine whether or not a particular driver is currently assigned
2907 ****************************************************************************/
2908 BOOL printer_driver_in_use (char *arch, char *driver)
2910 TDB_DATA kbuf, newkey, dbuf;
2911 NT_PRINTER_INFO_LEVEL_2 info;
2917 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
2919 /* loop through the printers.tdb and check for the drivername */
2920 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
2921 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
2924 dbuf = tdb_fetch(tdb_printers, kbuf);
2928 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
2931 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
2934 &info.default_priority,
2951 info.printprocessor,
2955 safe_free(dbuf.dptr);
2958 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
2963 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
2964 info.printername, info.drivername));
2966 if (strcmp(info.drivername, driver) == 0)
2968 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
2969 info.printername, driver));
2973 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
2977 /* report that the driver is in use by default */
2981 /****************************************************************************
2982 Remove a printer driver from the TDB. This assumes that the the driver was
2983 previously looked up.
2984 ***************************************************************************/
2985 uint32 delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
2992 get_short_archi(arch, i->environment);
2993 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
2994 arch, i->cversion, i->name);
2995 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
2998 kbuf.dsize=strlen(key)+1;
3000 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3001 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3002 return NT_STATUS_ACCESS_VIOLATION;
3005 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3008 return NT_STATUS_NOPROBLEMO;
3010 /****************************************************************************
3011 ****************************************************************************/
3012 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3013 fstring value, uint8 **data, uint32 *type, uint32 *len)
3015 /* right now that's enough ! */
3016 NT_PRINTER_PARAM *param;
3019 param=printer.info_2->specific;
3021 while (param != NULL && i < param_index) {
3029 /* exited because it exist */
3031 StrnCpy(value, param->value, sizeof(fstring)-1);
3032 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3035 ZERO_STRUCTP(*data);
3036 memcpy(*data, param->data, param->data_len);
3037 *len=param->data_len;
3041 /****************************************************************************
3042 ****************************************************************************/
3043 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3044 fstring value, uint8 **data, uint32 *type, uint32 *len)
3046 /* right now that's enough ! */
3047 NT_PRINTER_PARAM *param;
3049 DEBUG(10, ("get_specific_param\n"));
3051 param=printer.info_2->specific;
3053 while (param != NULL)
3055 #if 1 /* JRA - I think this should be case insensitive.... */
3056 if ( strequal(value, param->value)
3058 if ( !strcmp(value, param->value)
3060 && strlen(value)==strlen(param->value))
3068 DEBUGADD(10, ("get_specific_param: found one param\n"));
3069 /* exited because it exist */
3072 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3075 memcpy(*data, param->data, param->data_len);
3076 *len=param->data_len;
3078 DEBUGADD(10, ("get_specific_param: exit true\n"));
3081 DEBUGADD(10, ("get_specific_param: exit false\n"));
3085 /****************************************************************************
3086 Store a security desc for a printer.
3087 ****************************************************************************/
3089 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3091 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3092 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3094 TALLOC_CTX *mem_ctx = NULL;
3098 mem_ctx = talloc_init();
3099 if (mem_ctx == NULL)
3102 /* The old owner and group sids of the security descriptor are not
3103 present when new ACEs are added or removed by changing printer
3104 permissions through NT. If they are NULL in the new security
3105 descriptor then copy them over from the old one. */
3107 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3108 DOM_SID *owner_sid, *group_sid;
3109 SEC_ACL *dacl, *sacl;
3110 SEC_DESC *psd = NULL;
3113 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3115 /* Pick out correct owner and group sids */
3117 owner_sid = secdesc_ctr->sec->owner_sid ?
3118 secdesc_ctr->sec->owner_sid :
3119 old_secdesc_ctr->sec->owner_sid;
3121 group_sid = secdesc_ctr->sec->grp_sid ?
3122 secdesc_ctr->sec->grp_sid :
3123 old_secdesc_ctr->sec->grp_sid;
3125 dacl = secdesc_ctr->sec->dacl ?
3126 secdesc_ctr->sec->dacl :
3127 old_secdesc_ctr->sec->dacl;
3129 sacl = secdesc_ctr->sec->sacl ?
3130 secdesc_ctr->sec->sacl :
3131 old_secdesc_ctr->sec->sacl;
3133 /* Make a deep copy of the security descriptor */
3135 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3136 owner_sid, group_sid,
3141 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3144 if (!new_secdesc_ctr) {
3145 new_secdesc_ctr = secdesc_ctr;
3148 /* Store the security descriptor in a tdb */
3150 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3151 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3153 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3155 status = ERROR_INVALID_FUNCTION;
3159 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, printername);
3161 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3164 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3165 status = ERROR_INVALID_FUNCTION;
3168 /* Free malloc'ed memory */
3174 talloc_destroy(mem_ctx);
3178 /****************************************************************************
3179 Construct a default security descriptor buffer for a printer.
3180 ****************************************************************************/
3182 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3186 SEC_ACL *psa = NULL;
3187 SEC_DESC_BUF *sdb = NULL;
3188 SEC_DESC *psd = NULL;
3191 enum SID_NAME_USE name_type;
3193 /* Create an ACE where Everyone is allowed to print */
3195 init_sec_access(&sa, PRINTER_ACE_PRINT);
3196 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3197 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3199 /* Make the security descriptor owned by the Administrators group
3200 on the PDC of the domain. */
3202 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3203 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3207 /* Backup plan - make printer owned by admins or root.
3208 This should emulate a lanman printer as security
3209 settings can't be changed. */
3211 sid_peek_rid(&owner_sid, &owner_rid);
3213 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3214 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3215 owner_rid != DOMAIN_USER_RID_ADMIN &&
3216 !lookup_name("root", &owner_sid, &name_type)) {
3217 sid_copy(&owner_sid, &global_sid_World);
3221 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3222 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3223 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3224 SEC_ACE_FLAG_INHERIT_ONLY);
3226 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3227 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3228 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3230 /* The ACL revision number in rpc_secdesc.h differs from the one
3231 created by NT when setting ACE entries in printer
3232 descriptors. NT4 complains about the property being edited by a
3235 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3236 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3238 NULL, psa, &sd_size);
3242 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3246 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3248 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3249 (unsigned int)sd_size));
3254 /****************************************************************************
3255 Get a security desc for a printer.
3256 ****************************************************************************/
3258 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3264 if ((temp = strchr_m(printername + 2, '\\'))) {
3265 printername = temp + 1;
3268 /* Fetch security descriptor from tdb */
3270 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, printername);
3272 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3273 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3275 DEBUG(4,("using default secdesc for %s\n", printername));
3277 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3284 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3285 this security descriptor has been created when winbindd was
3286 down. Take ownership of security descriptor. */
3288 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3290 enum SID_NAME_USE name_type;
3292 /* Change sd owner to workgroup administrator */
3294 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3296 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3297 SEC_DESC *psd = NULL;
3302 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3304 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3306 (*secdesc_ctr)->sec->grp_sid,
3307 (*secdesc_ctr)->sec->sacl,
3308 (*secdesc_ctr)->sec->dacl,
3311 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3313 /* Swap with other one */
3315 *secdesc_ctr = new_secdesc_ctr;
3319 nt_printing_setsec(printername, *secdesc_ctr);
3323 if (DEBUGLEVEL >= 10) {
3324 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3327 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3328 printername, the_acl->num_aces));
3330 for (i = 0; i < the_acl->num_aces; i++) {
3333 sid_to_string(sid_str, &the_acl->ace[i].sid);
3335 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3336 the_acl->ace[i].type, the_acl->ace[i].flags,
3337 the_acl->ace[i].info.mask));
3347 1: level not implemented
3348 2: file doesn't exist
3349 3: can't allocate memory
3350 4: can't free memory
3351 5: non existant struct
3355 A printer and a printer driver are 2 different things.
3356 NT manages them separatelly, Samba does the same.
3357 Why ? Simply because it's easier and it makes sense !
3359 Now explanation: You have 3 printers behind your samba server,
3360 2 of them are the same make and model (laser A and B). But laser B
3361 has an 3000 sheet feeder and laser A doesn't such an option.
3362 Your third printer is an old dot-matrix model for the accounting :-).
3364 If the /usr/local/samba/lib directory (default dir), you will have
3365 5 files to describe all of this.
3367 3 files for the printers (1 by printer):
3370 NTprinter_accounting
3371 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3372 NTdriver_printer model X
3373 NTdriver_printer model Y
3375 jfm: I should use this comment for the text file to explain
3376 same thing for the forms BTW.
3377 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3381 /* Convert generic access rights to printer object specific access rights.
3382 It turns out that NT4 security descriptors use generic access rights and
3383 NT5 the object specific ones. */
3385 void map_printer_permissions(SEC_DESC *sd)
3389 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3390 se_map_generic(&sd->dacl->ace[i].info.mask,
3391 &printer_generic_mapping);
3395 /****************************************************************************
3396 Check a user has permissions to perform the given operation. We use the
3397 permission constants defined in include/rpc_spoolss.h to check the various
3398 actions we perform when checking printer access.
3400 PRINTER_ACCESS_ADMINISTER:
3401 print_queue_pause, print_queue_resume, update_printer_sec,
3402 update_printer, spoolss_addprinterex_level_2,
3403 _spoolss_setprinterdata
3408 JOB_ACCESS_ADMINISTER:
3409 print_job_delete, print_job_pause, print_job_resume,
3412 ****************************************************************************/
3413 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3415 SEC_DESC_BUF *secdesc = NULL;
3416 uint32 access_granted, status;
3419 TALLOC_CTX *mem_ctx = NULL;
3420 extern struct current_user current_user;
3422 /* If user is NULL then use the current_user structure */
3424 if (!user) user = ¤t_user;
3426 /* Always allow root or printer admins to do anything */
3428 if (user->uid == 0 ||
3429 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3433 /* Get printer name */
3435 pname = PRINTERNAME(snum);
3437 if (!pname || !*pname) {
3442 /* Get printer security descriptor */
3444 if(!(mem_ctx = talloc_init())) {
3449 nt_printing_getsec(mem_ctx, pname, &secdesc);
3451 if (access_type == JOB_ACCESS_ADMINISTER) {
3452 SEC_DESC_BUF *parent_secdesc = secdesc;
3454 /* Create a child security descriptor to check permissions
3455 against. This is because print jobs are child objects
3456 objects of a printer. */
3458 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3460 /* Now this is the bit that really confuses me. The access
3461 type needs to be changed from JOB_ACCESS_ADMINISTER to
3462 PRINTER_ACCESS_ADMINISTER for this to work. Something
3463 to do with the child (job) object becoming like a
3466 access_type = PRINTER_ACCESS_ADMINISTER;
3471 map_printer_permissions(secdesc->sec);
3473 result = se_access_check(secdesc->sec, user, access_type,
3474 &access_granted, &status);
3476 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3478 talloc_destroy(mem_ctx);
3486 /****************************************************************************
3487 Check the time parameters allow a print operation.
3488 *****************************************************************************/
3490 BOOL print_time_access_check(int snum)
3492 NT_PRINTER_INFO_LEVEL *printer = NULL;
3494 time_t now = time(NULL);
3498 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3501 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3505 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3507 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3510 free_a_printer(&printer, 2);
3518 /****************************************************************************
3519 Attempt to write a default device.
3520 *****************************************************************************/
3522 uint32 printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3524 NT_PRINTER_INFO_LEVEL *printer = NULL;
3529 * Don't bother if no default devicemode was sent.
3532 if (printer_default->devmode_cont.devmode == NULL)
3535 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3536 return ERROR_ACCESS_DENIED;
3539 * Just ignore it if we already have a devmode.
3542 if (printer->info_2->devmode != NULL)
3546 * We don't have a devicemode and we're trying to write
3547 * one. Check we have the access needed.
3549 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3551 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3552 PRINTER_ACCESS_ADMINISTER) {
3553 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3554 result = ERROR_ACCESS_DENIED;
3558 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3559 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3560 lp_servicename(snum) ));
3561 result = ERROR_ACCESS_DENIED;
3562 /*result = NT_STATUS_NOPROBLEMO;*/
3566 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3569 * Convert the on the wire devicemode format to the internal one.
3572 if (!convert_devicemode(printer->info_2->printername,
3573 printer_default->devmode_cont.devmode,
3574 &printer->info_2->devmode)) {
3575 result = ERROR_NOT_ENOUGH_MEMORY;
3580 * Finally write back to the tdb.
3583 if (add_a_printer(*printer, 2)!=0) {
3584 result = ERROR_ACCESS_DENIED;
3590 free_a_printer(&printer, 2);