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_forms; /* used for forms files */
30 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
31 static TDB_CONTEXT *tdb_printers; /* used for printers files */
33 #define FORMS_PREFIX "FORMS/"
34 #define DRIVERS_PREFIX "DRIVERS/"
35 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
36 #define PRINTERS_PREFIX "PRINTERS/"
37 #define SECDESC_PREFIX "SECDESC/"
39 #define NTDRIVERS_DATABASE_VERSION_1 1
40 #define NTDRIVERS_DATABASE_VERSION_2 2
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_2
44 /* Map generic permissions to printer object specific permissions */
46 struct generic_mapping printer_generic_mapping = {
53 /* We need one default form to support our default printer. Msoft adds the
54 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
55 array index). Letter is always first, so (for the current code) additions
56 always put things in the correct order. */
57 static nt_forms_struct default_forms[] = {
58 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
59 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
60 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
61 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
62 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
63 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
64 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
65 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
66 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
67 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
68 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
69 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
70 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
71 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
72 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
73 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
74 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
75 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
76 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
77 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
78 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
79 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
80 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
81 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
82 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
83 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
84 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
85 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
86 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
87 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
88 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
89 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
90 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
91 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
92 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
93 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
94 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
95 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
96 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
97 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
98 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
99 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
100 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
101 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
102 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
103 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
104 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
105 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
106 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
107 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
108 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
109 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
110 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
111 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
112 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
113 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
114 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
115 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
116 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
117 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
118 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
119 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
120 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
121 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
122 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
123 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
124 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
125 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
126 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
127 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
128 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
129 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
130 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
131 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
132 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
133 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
134 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
135 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
136 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
137 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
138 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
139 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
140 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
141 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
142 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
143 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
144 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
145 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
146 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
147 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
148 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
149 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
150 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
151 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
152 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
153 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
154 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
155 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
156 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
157 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
158 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
159 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
160 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
161 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
162 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
163 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
164 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
165 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
166 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
167 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
168 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
169 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
170 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
171 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
172 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
173 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
174 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
175 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
178 static BOOL upgrade_to_version_2(void)
180 TDB_DATA kbuf, newkey, dbuf;
182 DEBUG(0,("upgrade_to_version_2: upgrading print tdb's to version 2\n"));
184 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
185 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
187 dbuf = tdb_fetch(tdb_drivers, kbuf);
189 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
190 DEBUG(0,("upgrade_to_version_2:moving form\n"));
191 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
192 DEBUG(0,("upgrade_to_version_2: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
195 if (tdb_delete(tdb_drivers, kbuf) != 0) {
196 DEBUG(0,("upgrade_to_version_2: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
201 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
202 DEBUG(0,("upgrade_to_version_2:moving printer\n"));
203 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
204 DEBUG(0,("upgrade_to_version_2: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
207 if (tdb_delete(tdb_drivers, kbuf) != 0) {
208 DEBUG(0,("upgrade_to_version_2: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
213 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
214 DEBUG(0,("upgrade_to_version_2:moving secdesc\n"));
215 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
216 DEBUG(0,("upgrade_to_version_2: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
219 if (tdb_delete(tdb_drivers, kbuf) != 0) {
220 DEBUG(0,("upgrade_to_version_2: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
225 safe_free(dbuf.dptr);
231 /****************************************************************************
232 open the NT printing tdb
233 ****************************************************************************/
234 BOOL nt_printing_init(void)
236 static pid_t local_pid;
237 char *vstring = "INFO/version";
239 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
242 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, USE_TDB_MMAP_FLAG, O_RDWR|O_CREAT, 0600);
244 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
245 lock_path("ntdrivers.tdb"), strerror(errno) ));
249 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, USE_TDB_MMAP_FLAG, O_RDWR|O_CREAT, 0600);
251 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
252 lock_path("ntprinters.tdb"), strerror(errno) ));
256 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, USE_TDB_MMAP_FLAG, O_RDWR|O_CREAT, 0600);
258 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
259 lock_path("ntforms.tdb"), strerror(errno) ));
263 local_pid = sys_getpid();
265 /* handle a Samba upgrade */
266 tdb_lock_bystring(tdb_drivers, vstring);
267 if (tdb_fetch_int(tdb_drivers, vstring) != NTDRIVERS_DATABASE_VERSION) {
269 if (tdb_fetch_int(tdb_drivers, vstring) == NTDRIVERS_DATABASE_VERSION_1) {
270 if (!upgrade_to_version_2())
273 tdb_traverse(tdb_drivers, (tdb_traverse_func)tdb_delete, NULL);
275 tdb_store_int(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
277 tdb_unlock_bystring(tdb_drivers, vstring);
282 /****************************************************************************
283 get builtin form struct list
284 ****************************************************************************/
285 int get_builtin_ntforms(nt_forms_struct **list)
287 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
288 return sizeof(default_forms) / sizeof(default_forms[0]);
291 /****************************************************************************
292 get a builtin form struct
293 ****************************************************************************/
295 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
299 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
300 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
301 count = sizeof(default_forms) / sizeof(default_forms[0]);
302 for (i=0;i<count;i++) {
303 if (strequal(form_name,default_forms[i].name)) {
304 DEBUGADD(6,("Found builtin form %s \n", form_name));
305 memcpy(form,&default_forms[i],sizeof(*form));
313 /****************************************************************************
314 get a form struct list
315 ****************************************************************************/
316 int get_ntforms(nt_forms_struct **list)
318 TDB_DATA kbuf, newkey, dbuf;
320 nt_forms_struct form;
325 for (kbuf = tdb_firstkey(tdb_forms);
327 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
328 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
330 dbuf = tdb_fetch(tdb_forms, kbuf);
331 if (!dbuf.dptr) continue;
333 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
334 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
335 &i, &form.flag, &form.width, &form.length, &form.left,
336 &form.top, &form.right, &form.bottom);
337 safe_free(dbuf.dptr);
338 if (ret != dbuf.dsize) continue;
340 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
342 DEBUG(0,("get_ntforms: Realloc fail.\n"));
354 /****************************************************************************
355 write a form struct list
356 ****************************************************************************/
357 int write_ntforms(nt_forms_struct **list, int number)
364 for (i=0;i<number;i++) {
365 /* save index, so list is rebuilt in correct order */
366 len = tdb_pack(buf, sizeof(buf), "dddddddd",
367 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
368 (*list)[i].left, (*list)[i].top, (*list)[i].right,
370 if (len > sizeof(buf)) break;
371 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
372 kbuf.dsize = strlen(key)+1;
376 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
382 /****************************************************************************
383 add a form struct at the end of the list
384 ****************************************************************************/
385 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
393 * NT tries to add forms even when
394 * they are already in the base
395 * only update the values if already present
400 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
401 for (n=0; n<*count; n++) {
402 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
403 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
410 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
411 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
415 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
419 (*list)[n].flag=form->flags;
420 (*list)[n].width=form->size_x;
421 (*list)[n].length=form->size_y;
422 (*list)[n].left=form->left;
423 (*list)[n].top=form->top;
424 (*list)[n].right=form->right;
425 (*list)[n].bottom=form->bottom;
430 /****************************************************************************
431 delete a named form struct
432 ****************************************************************************/
433 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
442 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
444 for (n=0; n<*count; n++) {
445 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
446 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
452 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
453 *ret = ERRinvalidparam;
457 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
458 kbuf.dsize = strlen(key)+1;
460 if (tdb_delete(tdb_forms, kbuf) != 0) {
468 /****************************************************************************
470 ****************************************************************************/
471 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
475 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
477 DEBUG(106, ("[%s]\n", form_name));
478 for (n=0; n<count; n++)
480 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
481 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
485 if (n==count) return;
487 (*list)[n].flag=form->flags;
488 (*list)[n].width=form->size_x;
489 (*list)[n].length=form->size_y;
490 (*list)[n].left=form->left;
491 (*list)[n].top=form->top;
492 (*list)[n].right=form->right;
493 (*list)[n].bottom=form->bottom;
496 /****************************************************************************
497 get the nt drivers list
499 traverse the database and look-up the matching names
500 ****************************************************************************/
501 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
507 TDB_DATA kbuf, newkey;
509 get_short_archi(short_archi, architecture);
510 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
512 for (kbuf = tdb_firstkey(tdb_drivers);
514 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
515 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
517 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
518 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
523 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
530 /****************************************************************************
531 function to do the mapping between the long architecture name and
533 ****************************************************************************/
534 BOOL get_short_archi(char *short_archi, char *long_archi)
541 struct table archi_table[]=
543 {"Windows 4.0", "WIN40" },
544 {"Windows NT x86", "W32X86" },
545 {"Windows NT R4000", "W32MIPS" },
546 {"Windows NT Alpha_AXP", "W32ALPHA" },
547 {"Windows NT PowerPC", "W32PPC" },
553 DEBUG(107,("Getting architecture dependant directory\n"));
556 } while ( (archi_table[i].long_archi!=NULL ) &&
557 StrCaseCmp(long_archi, archi_table[i].long_archi) );
559 if (archi_table[i].long_archi==NULL) {
560 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
564 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
566 DEBUGADD(108,("index: [%d]\n", i));
567 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
568 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
573 /****************************************************************************
574 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
575 There are two case to be covered here: PE (Portable Executable) and NE (New
576 Executable) files. Both files support the same INFO structure, but PE files
577 store the signature in unicode, and NE files store it as !unicode.
578 ****************************************************************************/
579 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
586 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
587 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
588 fname, PE_HEADER_SIZE));
592 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
593 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
594 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
596 goto no_version_info;
599 /* Is this really a DOS header? */
600 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
601 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
602 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
603 goto no_version_info;
606 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
607 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
608 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
610 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
611 goto no_version_info;
614 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
615 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
617 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
618 goto no_version_info;
621 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
622 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
624 int section_table_bytes;
626 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
627 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
628 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
629 /* At this point, we assume the file is in error. It still could be somthing
630 * else besides a PE file, but it unlikely at this point.
635 /* get the section table */
636 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
637 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
639 if ((buf=malloc(section_table_bytes)) == NULL) {
640 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
641 fname, section_table_bytes));
645 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
646 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
651 /* Iterate the section table looking for the resource section ".rsrc" */
652 for (i = 0; i < num_sections; i++) {
653 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
655 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
656 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
657 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
660 if ((buf=malloc(section_bytes)) == NULL) {
661 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
662 fname, section_bytes));
666 /* Seek to the start of the .rsrc section info */
667 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
668 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
673 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
674 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
679 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
680 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
681 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
682 /* Align to next long address */
683 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
685 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
686 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
687 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
689 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
690 fname, *major, *minor,
691 (*major>>16)&0xffff, *major&0xffff,
692 (*minor>>16)&0xffff, *minor&0xffff));
701 /* Version info not found, fall back to origin date/time */
702 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
706 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
707 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
708 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
709 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
710 /* At this point, we assume the file is in error. It still could be somthing
711 * else besides a NE file, but it unlikely at this point. */
715 /* Allocate a bit more space to speed up things */
717 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
718 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
719 fname, PE_HEADER_SIZE));
723 /* This is a HACK! I got tired of trying to sort through the messy
724 * 'NE' file format. If anyone wants to clean this up please have at
725 * it, but this works. 'NE' files will eventually fade away. JRR */
726 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
727 /* Cover case that should not occur in a well formed 'NE' .dll file */
728 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
730 for(i=0; i<byte_count; i++) {
731 /* Fast skip past data that can't possibly match */
732 if (buf[i] != 'V') continue;
734 /* Potential match data crosses buf boundry, move it to beginning
735 * of buf, and fill the buf with as much as it will hold. */
736 if (i>byte_count-VS_VERSION_INFO_SIZE) {
739 memcpy(buf, &buf[i], byte_count-i);
740 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
741 (byte_count-i))) < 0) {
743 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
748 byte_count = bc + (byte_count - i);
749 if (byte_count<VS_VERSION_INFO_SIZE) break;
754 /* Check that the full signature string and the magic number that
755 * follows exist (not a perfect solution, but the chances that this
756 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
757 * twice, as it is simpler to read the code. */
758 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
759 /* Compute skip alignment to next long address */
760 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
761 sizeof(VS_SIGNATURE)) & 3;
762 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
764 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
765 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
766 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
767 fname, *major, *minor,
768 (*major>>16)&0xffff, *major&0xffff,
769 (*minor>>16)&0xffff, *minor&0xffff));
776 /* Version info not found, fall back to origin date/time */
777 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
782 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
783 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
784 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
795 /****************************************************************************
796 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
797 share one or more files. During the MS installation process files are checked
798 to insure that only a newer version of a shared file is installed over an
799 older version. There are several possibilities for this comparison. If there
800 is no previous version, the new one is newer (obviously). If either file is
801 missing the version info structure, compare the creation date (on Unix use
802 the modification date). Otherwise chose the numerically larger version number.
803 ****************************************************************************/
804 static int file_version_is_newer(connection_struct *conn, fstring new_file,
807 BOOL use_version = True;
812 time_t new_create_time;
816 time_t old_create_time;
820 files_struct *fsp = NULL;
822 SMB_STRUCT_STAT stat_buf;
826 ZERO_STRUCT(stat_buf);
827 new_create_time = (time_t)0;
828 old_create_time = (time_t)0;
830 /* Get file version info (if available) for previous file (if it exists) */
831 pstrcpy(filepath, old_file);
833 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
835 fsp = open_file_shared(conn, filepath, &stat_buf,
836 SET_OPEN_MODE(DOS_OPEN_RDONLY),
837 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
838 0, 0, &access_mode, &action);
840 /* Old file not found, so by definition new file is in fact newer */
841 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
846 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
847 if (ret == -1) goto error_exit;
850 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
853 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
854 old_create_time = st.st_mtime;
855 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
858 close_file(fsp, True);
860 /* Get file version info (if available) for new file */
861 pstrcpy(filepath, new_file);
862 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
864 fsp = open_file_shared(conn, filepath, &stat_buf,
865 SET_OPEN_MODE(DOS_OPEN_RDONLY),
866 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
867 0, 0, &access_mode, &action);
869 /* New file not found, this shouldn't occur if the caller did its job */
870 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
875 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
876 if (ret == -1) goto error_exit;
879 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
882 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
883 new_create_time = st.st_mtime;
884 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
887 close_file(fsp, True);
890 /* Compare versions and choose the larger version number */
891 if (new_major > old_major ||
892 (new_major == old_major && new_minor > old_minor)) {
894 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
898 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
903 /* Compare modification time/dates and choose the newest time/date */
904 if (new_create_time > old_create_time) {
905 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
909 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
916 close_file(fsp, True);
920 /****************************************************************************
921 Determine the correct cVersion associated with an architecture and driver
922 ****************************************************************************/
923 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
924 struct current_user *user, uint32 *perr)
933 files_struct *fsp = NULL;
937 connection_struct *conn;
941 /* If architecture is Windows 95/98/ME, the version is always 0. */
942 if (strcmp(architecture, "WIN40") == 0) {
943 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
948 pass = sys_getpwuid(user->uid);
950 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
951 (unsigned int)user->uid ));
958 /* connect to the print$ share under the same account as the user connected
960 fstrcpy(user_name, pass->pw_name );
961 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
963 /* Null password is ok - we are already an authenticated user... */
965 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
968 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
969 *perr = (uint32)ecode;
973 /* Save who we are - we are temporarily becoming the connection user. */
976 if (!become_user(conn, conn->vuid)) {
977 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
983 /* Open the driver file (Portable Executable format) and determine the
984 * deriver the cversion. */
985 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
987 unix_convert(driverpath,conn,NULL,&bad_path,&st);
989 fsp = open_file_shared(conn, driverpath, &st,
990 SET_OPEN_MODE(DOS_OPEN_RDONLY),
991 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
992 0, 0, &access_mode, &action);
994 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1002 int ret = get_file_version(fsp, driverpath, &major, &minor);
1003 if (ret == -1) goto error_exit;
1006 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1011 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1012 * for more details. Version in this case is not just the version of the
1013 * file, but the version in the sense of kernal mode (2) vs. user mode
1014 * (3) drivers. Other bits of the version fields are the version info.
1017 cversion = major & 0x0000ffff;
1019 case 2: /* WinNT drivers */
1020 case 3: /* Win2K drivers */
1024 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1025 driverpath, cversion));
1029 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1030 driverpath, major, minor));
1033 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1034 driverpath, cversion));
1036 close_file(fsp, True);
1037 close_cnum(conn, user->vuid);
1044 close_file(fsp, True);
1046 close_cnum(conn, user->vuid);
1051 /****************************************************************************
1052 ****************************************************************************/
1053 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1054 struct current_user *user)
1056 fstring architecture;
1062 /* clean up the driver name.
1063 * we can get .\driver.dll
1064 * or worse c:\windows\system\driver.dll !
1066 /* using an intermediate string to not have overlaping memcpy()'s */
1067 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1068 fstrcpy(new_name, p+1);
1069 fstrcpy(driver->driverpath, new_name);
1072 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1073 fstrcpy(new_name, p+1);
1074 fstrcpy(driver->datafile, new_name);
1077 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1078 fstrcpy(new_name, p+1);
1079 fstrcpy(driver->configfile, new_name);
1082 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1083 fstrcpy(new_name, p+1);
1084 fstrcpy(driver->helpfile, new_name);
1087 if (driver->dependentfiles) {
1088 for (i=0; *driver->dependentfiles[i]; i++) {
1089 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1090 fstrcpy(new_name, p+1);
1091 fstrcpy(driver->dependentfiles[i], new_name);
1096 get_short_archi(architecture, driver->environment);
1098 /* jfm:7/16/2000 the client always sends the cversion=0.
1099 * The server should check which version the driver is by reading
1100 * the PE header of driver->driverpath.
1102 * For Windows 95/98 the version is 0 (so the value sent is correct)
1103 * For Windows NT (the architecture doesn't matter)
1104 * NT 3.1: cversion=0
1105 * NT 3.5/3.51: cversion=1
1109 if ((driver->cversion = get_correct_cversion( architecture,
1110 driver->driverpath, user, &err)) == -1)
1113 return NT_STATUS_NOPROBLEMO;
1116 /****************************************************************************
1117 ****************************************************************************/
1118 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1119 struct current_user *user)
1121 fstring architecture;
1127 /* clean up the driver name.
1128 * we can get .\driver.dll
1129 * or worse c:\windows\system\driver.dll !
1131 /* using an intermediate string to not have overlaping memcpy()'s */
1132 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1133 fstrcpy(new_name, p+1);
1134 fstrcpy(driver->driverpath, new_name);
1137 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1138 fstrcpy(new_name, p+1);
1139 fstrcpy(driver->datafile, new_name);
1142 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1143 fstrcpy(new_name, p+1);
1144 fstrcpy(driver->configfile, new_name);
1147 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1148 fstrcpy(new_name, p+1);
1149 fstrcpy(driver->helpfile, new_name);
1152 if (driver->dependentfiles) {
1153 for (i=0; *driver->dependentfiles[i]; i++) {
1154 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1155 fstrcpy(new_name, p+1);
1156 fstrcpy(driver->dependentfiles[i], new_name);
1161 get_short_archi(architecture, driver->environment);
1163 /* jfm:7/16/2000 the client always sends the cversion=0.
1164 * The server should check which version the driver is by reading
1165 * the PE header of driver->driverpath.
1167 * For Windows 95/98 the version is 0 (so the value sent is correct)
1168 * For Windows NT (the architecture doesn't matter)
1169 * NT 3.1: cversion=0
1170 * NT 3.5/3.51: cversion=1
1174 if ((driver->version = get_correct_cversion(architecture,
1175 driver->driverpath, user, &err)) == -1)
1178 return NT_STATUS_NOPROBLEMO;
1181 /****************************************************************************
1182 ****************************************************************************/
1183 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1184 uint32 level, struct current_user *user)
1189 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1190 driver=driver_abstract.info_3;
1191 return clean_up_driver_struct_level_3(driver, user);
1195 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1196 driver=driver_abstract.info_6;
1197 return clean_up_driver_struct_level_6(driver, user);
1200 return ERRinvalidparam;
1204 /****************************************************************************
1205 This function sucks and should be replaced. JRA.
1206 ****************************************************************************/
1208 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1210 dst->cversion = src->version;
1212 fstrcpy( dst->name, src->name);
1213 fstrcpy( dst->environment, src->environment);
1214 fstrcpy( dst->driverpath, src->driverpath);
1215 fstrcpy( dst->datafile, src->datafile);
1216 fstrcpy( dst->configfile, src->configfile);
1217 fstrcpy( dst->helpfile, src->helpfile);
1218 fstrcpy( dst->monitorname, src->monitorname);
1219 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1220 dst->dependentfiles = src->dependentfiles;
1223 #if 0 /* Debugging function */
1225 static char* ffmt(unsigned char *c){
1227 static char ffmt_str[17];
1229 for (i=0; i<16; i++) {
1230 if ((c[i] < ' ') || (c[i] > '~'))
1241 /****************************************************************************
1242 ****************************************************************************/
1243 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1245 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1246 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1247 fstring architecture;
1253 connection_struct *conn;
1256 struct passwd *pass;
1262 memset(inbuf, '\0', sizeof(inbuf));
1263 memset(outbuf, '\0', sizeof(outbuf));
1266 driver=driver_abstract.info_3;
1267 else if (level==6) {
1268 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1269 driver = &converted_driver;
1271 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1275 get_short_archi(architecture, driver->environment);
1278 pass = sys_getpwuid(user->uid);
1280 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1281 (unsigned int)user->uid ));
1287 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1288 fstrcpy(user_name, pass->pw_name );
1289 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1291 /* Null password is ok - we are already an authenticated user... */
1293 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1296 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1297 *perr = (uint32)ecode;
1302 * Save who we are - we are temporarily becoming the connection user.
1307 if (!become_user(conn, conn->vuid)) {
1308 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1314 * make the directories version and version\driver_name
1315 * under the architecture directory.
1317 DEBUG(5,("Creating first directory\n"));
1318 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1319 mkdir_internal(conn, inbuf, outbuf, new_dir);
1321 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1322 * listed for this driver which has already been moved, skip it (note:
1323 * drivers may list the same file name several times. Then check if the
1324 * file already exists in archi\cversion\, if so, check that the version
1325 * info (or time stamps if version info is unavailable) is newer (or the
1326 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1327 * Otherwise, delete the file.
1329 * If a file is not moved to archi\cversion\ because of an error, all the
1330 * rest of the 'unmoved' driver files are removed from archi\. If one or
1331 * more of the driver's files was already moved to archi\cversion\, it
1332 * potentially leaves the driver in a partially updated state. Version
1333 * trauma will most likely occur if an client attempts to use any printer
1334 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1335 * done is appropriate... later JRR
1338 DEBUG(5,("Moving files now !\n"));
1340 if (driver->driverpath && strlen(driver->driverpath)) {
1341 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1342 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1343 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1344 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1345 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1346 new_name, old_name));
1347 *perr = (uint32)SVAL(outbuf,smb_err);
1348 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1353 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1356 if (driver->datafile && strlen(driver->datafile)) {
1357 if (!strequal(driver->datafile, driver->driverpath)) {
1358 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1359 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1360 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1361 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1362 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1363 new_name, old_name));
1364 *perr = (uint32)SVAL(outbuf,smb_err);
1365 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1370 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1374 if (driver->configfile && strlen(driver->configfile)) {
1375 if (!strequal(driver->configfile, driver->driverpath) &&
1376 !strequal(driver->configfile, driver->datafile)) {
1377 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1378 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1379 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1380 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1381 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1382 new_name, old_name));
1383 *perr = (uint32)SVAL(outbuf,smb_err);
1384 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1389 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1393 if (driver->helpfile && strlen(driver->helpfile)) {
1394 if (!strequal(driver->helpfile, driver->driverpath) &&
1395 !strequal(driver->helpfile, driver->datafile) &&
1396 !strequal(driver->helpfile, driver->configfile)) {
1397 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1398 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1399 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1400 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1401 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1402 new_name, old_name));
1403 *perr = (uint32)SVAL(outbuf,smb_err);
1404 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1409 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1413 if (driver->dependentfiles) {
1414 for (i=0; *driver->dependentfiles[i]; i++) {
1415 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1416 !strequal(driver->dependentfiles[i], driver->datafile) &&
1417 !strequal(driver->dependentfiles[i], driver->configfile) &&
1418 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1420 for (j=0; j < i; j++) {
1421 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1426 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1427 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1428 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1429 if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
1430 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1431 new_name, old_name));
1432 *perr = (uint32)SVAL(outbuf,smb_err);
1433 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1438 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1444 close_cnum(conn, user->vuid);
1447 return ver == -1 ? False : True;
1450 /****************************************************************************
1451 ****************************************************************************/
1452 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1455 fstring architecture;
1461 TDB_DATA kbuf, dbuf;
1463 get_short_archi(architecture, driver->environment);
1465 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1466 * \\server is added in the rpc server layer.
1467 * It does make sense to NOT store the server's name in the printer TDB.
1470 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1472 /* .inf files do not always list a file for each of the four standard files.
1473 * Don't prepend a path to a null filename, or client claims:
1474 * "The server on which the printer resides does not have a suitable
1475 * <printer driver name> printer driver installed. Click OK if you
1476 * wish to install the driver on your local machine."
1478 if (strlen(driver->driverpath)) {
1479 fstrcpy(temp_name, driver->driverpath);
1480 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1483 if (strlen(driver->datafile)) {
1484 fstrcpy(temp_name, driver->datafile);
1485 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1488 if (strlen(driver->configfile)) {
1489 fstrcpy(temp_name, driver->configfile);
1490 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1493 if (strlen(driver->helpfile)) {
1494 fstrcpy(temp_name, driver->helpfile);
1495 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1498 if (driver->dependentfiles) {
1499 for (i=0; *driver->dependentfiles[i]; i++) {
1500 fstrcpy(temp_name, driver->dependentfiles[i]);
1501 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1505 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1507 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1514 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1517 driver->environment,
1522 driver->monitorname,
1523 driver->defaultdatatype);
1525 if (driver->dependentfiles) {
1526 for (i=0; *driver->dependentfiles[i]; i++) {
1527 len += tdb_pack(buf+len, buflen-len, "f",
1528 driver->dependentfiles[i]);
1532 if (len != buflen) {
1535 tb = (char *)Realloc(buf, len);
1537 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1548 kbuf.dsize = strlen(key)+1;
1552 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1556 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1562 /****************************************************************************
1563 ****************************************************************************/
1564 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1566 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1569 info3.cversion = driver->version;
1570 fstrcpy(info3.name,driver->name);
1571 fstrcpy(info3.environment,driver->environment);
1572 fstrcpy(info3.driverpath,driver->driverpath);
1573 fstrcpy(info3.datafile,driver->datafile);
1574 fstrcpy(info3.configfile,driver->configfile);
1575 fstrcpy(info3.helpfile,driver->helpfile);
1576 fstrcpy(info3.monitorname,driver->monitorname);
1577 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1578 info3.dependentfiles = driver->dependentfiles;
1580 return add_a_printer_driver_3(&info3);
1584 /****************************************************************************
1585 ****************************************************************************/
1586 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1588 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1592 fstrcpy(info.name, in_prt);
1593 fstrcpy(info.defaultdatatype, "RAW");
1595 fstrcpy(info.driverpath, "");
1596 fstrcpy(info.datafile, "");
1597 fstrcpy(info.configfile, "");
1598 fstrcpy(info.helpfile, "");
1600 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1603 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1604 fstrcpy(info.dependentfiles[0], "");
1606 *info_ptr = memdup(&info, sizeof(info));
1611 /****************************************************************************
1612 ****************************************************************************/
1613 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1615 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1616 TDB_DATA kbuf, dbuf;
1617 fstring architecture;
1622 ZERO_STRUCT(driver);
1624 get_short_archi(architecture, in_arch);
1626 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1628 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1631 kbuf.dsize = strlen(key)+1;
1633 dbuf = tdb_fetch(tdb_drivers, kbuf);
1635 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1637 if (!dbuf.dptr) return 5;
1639 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1648 driver.defaultdatatype);
1651 while (len < dbuf.dsize) {
1654 tddfs = (fstring *)Realloc(driver.dependentfiles,
1655 sizeof(fstring)*(i+2));
1656 if (tddfs == NULL) {
1657 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1660 else driver.dependentfiles = tddfs;
1662 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1663 &driver.dependentfiles[i]);
1666 if (driver.dependentfiles != NULL)
1667 fstrcpy(driver.dependentfiles[i], "");
1669 safe_free(dbuf.dptr);
1671 if (len != dbuf.dsize) {
1672 if (driver.dependentfiles != NULL)
1673 safe_free(driver.dependentfiles);
1675 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1678 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1683 /****************************************************************************
1684 ****************************************************************************/
1685 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1687 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1693 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1694 DEBUG(10,("driver key: [%s]\n", key));
1697 kbuf.dsize = strlen(key)+1;
1698 if (!tdb_exists(tdb_drivers, kbuf)) return False;
1701 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1703 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1704 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1705 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1706 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1707 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1708 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1709 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1711 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1712 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1713 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1715 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1716 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1717 pstrcat(line, info3->configfile);
1719 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1720 pstrcat(line, info3->datafile);
1722 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1723 pstrcat(line, info3->helpfile);
1725 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1726 pstrcat(line, info3->monitorname);
1728 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1731 for (i=0; info3->dependentfiles &&
1732 *info3->dependentfiles[i]; i++) {
1733 if (i) pstrcat(line, ","); /* don't end in a "," */
1734 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1735 pstrcat(line, info3->dependentfiles[i]);
1743 /****************************************************************************
1744 debugging function, dump at level 6 the struct in the logs
1745 ****************************************************************************/
1746 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1749 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1752 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1758 if (driver.info_3 == NULL)
1761 info3=driver.info_3;
1763 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1764 DEBUGADD(106,("name:[%s]\n", info3->name));
1765 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1766 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1767 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1768 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1769 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1770 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1771 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1773 for (i=0; info3->dependentfiles &&
1774 *info3->dependentfiles[i]; i++) {
1775 DEBUGADD(106,("dependentfile:[%s]\n",
1776 info3->dependentfiles[i]));
1783 DEBUGADD(1,("Level not implemented\n"));
1791 /****************************************************************************
1792 ****************************************************************************/
1793 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1797 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1799 if (!nt_devmode) return len;
1801 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1802 nt_devmode->devicename,
1803 nt_devmode->formname,
1805 nt_devmode->specversion,
1806 nt_devmode->driverversion,
1808 nt_devmode->driverextra,
1809 nt_devmode->orientation,
1810 nt_devmode->papersize,
1811 nt_devmode->paperlength,
1812 nt_devmode->paperwidth,
1815 nt_devmode->defaultsource,
1816 nt_devmode->printquality,
1819 nt_devmode->yresolution,
1820 nt_devmode->ttoption,
1821 nt_devmode->collate,
1822 nt_devmode->logpixels,
1825 nt_devmode->bitsperpel,
1826 nt_devmode->pelswidth,
1827 nt_devmode->pelsheight,
1828 nt_devmode->displayflags,
1829 nt_devmode->displayfrequency,
1830 nt_devmode->icmmethod,
1831 nt_devmode->icmintent,
1832 nt_devmode->mediatype,
1833 nt_devmode->dithertype,
1834 nt_devmode->reserved1,
1835 nt_devmode->reserved2,
1836 nt_devmode->panningwidth,
1837 nt_devmode->panningheight,
1838 nt_devmode->private);
1841 if (nt_devmode->private) {
1842 len += tdb_pack(buf+len, buflen-len, "B",
1843 nt_devmode->driverextra,
1844 nt_devmode->private);
1847 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1852 /****************************************************************************
1853 ****************************************************************************/
1854 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1858 while (param != NULL) {
1859 len += tdb_pack(buf+len, buflen-len, "pfdB",
1868 len += tdb_pack(buf+len, buflen-len, "p", param);
1874 /****************************************************************************
1875 delete a printer - this just deletes the printer info file, any open
1876 handles are not affected
1877 ****************************************************************************/
1878 uint32 del_a_printer(char *sharename)
1883 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1886 kbuf.dsize=strlen(key)+1;
1888 tdb_delete(tdb_printers, kbuf);
1892 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1893 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1894 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1895 /****************************************************************************
1896 ****************************************************************************/
1897 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1901 int buflen, len, ret;
1902 TDB_DATA kbuf, dbuf;
1905 * in addprinter: no servername and the printer is the name
1906 * in setprinter: servername is \\server
1907 * and printer is \\server\\printer
1909 * Samba manages only local printers.
1910 * we currently don't support things like path=\\other_server\printer
1913 if (info->servername[0]!='\0') {
1914 trim_string(info->printername, info->servername, NULL);
1915 trim_string(info->printername, "\\", NULL);
1916 info->servername[0]='\0';
1920 * JFM: one day I'll forget.
1921 * below that's info->portname because that's the SAMBA sharename
1922 * and I made NT 'thinks' it's the portname
1923 * the info->sharename is the thing you can name when you add a printer
1924 * that's the short-name when you create shared printer for 95/98
1925 * So I've made a limitation in SAMBA: you can only have 1 printer model
1926 * behind a SAMBA share.
1934 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1937 info->default_priority,
1954 info->printprocessor,
1958 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1960 len += pack_specifics(info->specific, buf+len, buflen-len);
1962 if (buflen != len) {
1965 tb = (char *)Realloc(buf, len);
1967 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1977 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1980 kbuf.dsize = strlen(key)+1;
1984 ret = tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
1988 DEBUG(8, ("error updating printer to tdb on disk\n"));
1992 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1993 info->sharename, info->drivername, info->portname, len));
1999 /****************************************************************************
2000 ****************************************************************************/
2001 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
2003 NT_PRINTER_PARAM *current;
2005 DEBUG(108,("add_a_specific_param\n"));
2007 (*param)->next=NULL;
2009 if (info_2->specific == NULL)
2011 info_2->specific=*param;
2015 current=info_2->specific;
2016 while (current->next != NULL) {
2017 current=current->next;
2019 current->next=*param;
2025 /****************************************************************************
2026 ****************************************************************************/
2027 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2029 NT_PRINTER_PARAM *current;
2030 NT_PRINTER_PARAM *previous;
2032 current=info_2->specific;
2035 if (current==NULL) return (False);
2037 if ( !strcmp(current->value, param->value) &&
2038 (strlen(current->value)==strlen(param->value)) ) {
2039 DEBUG(109,("deleting first value\n"));
2040 info_2->specific=current->next;
2041 safe_free(current->data);
2043 DEBUG(109,("deleted first value\n"));
2047 current=previous->next;
2049 while ( current!=NULL ) {
2050 if (!strcmp(current->value, param->value) &&
2051 strlen(current->value)==strlen(param->value) ) {
2052 DEBUG(109,("deleting current value\n"));
2053 previous->next=current->next;
2054 safe_free(current->data);
2056 DEBUG(109,("deleted current value\n"));
2060 previous=previous->next;
2061 current=current->next;
2066 /****************************************************************************
2067 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2068 ****************************************************************************/
2069 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2071 NT_PRINTER_PARAM *param = *param_ptr;
2076 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2079 safe_free(param->data);
2085 /****************************************************************************
2086 Malloc and return an NT devicemode.
2087 ****************************************************************************/
2089 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2092 * should I init this ones ???
2093 nt_devmode->devicename
2097 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2099 if (nt_devmode == NULL) {
2100 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2104 ZERO_STRUCTP(nt_devmode);
2106 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2107 fstrcpy(nt_devmode->devicename, adevice);
2109 fstrcpy(nt_devmode->formname, "Letter");
2111 nt_devmode->specversion = 0x0401;
2112 nt_devmode->driverversion = 0x0400;
2113 nt_devmode->size = 0x00DC;
2114 nt_devmode->driverextra = 0x0000;
2115 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2116 DEFAULTSOURCE | COPIES | SCALE |
2117 PAPERSIZE | ORIENTATION;
2118 nt_devmode->orientation = 1;
2119 nt_devmode->papersize = PAPER_LETTER;
2120 nt_devmode->paperlength = 0;
2121 nt_devmode->paperwidth = 0;
2122 nt_devmode->scale = 0x64;
2123 nt_devmode->copies = 01;
2124 nt_devmode->defaultsource = BIN_FORMSOURCE;
2125 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2126 nt_devmode->color = COLOR_MONOCHROME;
2127 nt_devmode->duplex = DUP_SIMPLEX;
2128 nt_devmode->yresolution = 0;
2129 nt_devmode->ttoption = TT_SUBDEV;
2130 nt_devmode->collate = COLLATE_FALSE;
2131 nt_devmode->icmmethod = 0;
2132 nt_devmode->icmintent = 0;
2133 nt_devmode->mediatype = 0;
2134 nt_devmode->dithertype = 0;
2136 /* non utilisés par un driver d'imprimante */
2137 nt_devmode->logpixels = 0;
2138 nt_devmode->bitsperpel = 0;
2139 nt_devmode->pelswidth = 0;
2140 nt_devmode->pelsheight = 0;
2141 nt_devmode->displayflags = 0;
2142 nt_devmode->displayfrequency = 0;
2143 nt_devmode->reserved1 = 0;
2144 nt_devmode->reserved2 = 0;
2145 nt_devmode->panningwidth = 0;
2146 nt_devmode->panningheight = 0;
2148 nt_devmode->private = NULL;
2152 /****************************************************************************
2153 Deepcopy an NT devicemode.
2154 ****************************************************************************/
2156 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2158 NT_DEVICEMODE *new_nt_devicemode = NULL;
2160 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2161 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2165 new_nt_devicemode->private = NULL;
2166 if (nt_devicemode->private != NULL) {
2167 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2168 safe_free(new_nt_devicemode);
2169 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2174 return new_nt_devicemode;
2177 /****************************************************************************
2178 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2179 ****************************************************************************/
2181 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2183 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2185 if(nt_devmode == NULL)
2188 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2190 if(nt_devmode->private)
2191 safe_free(nt_devmode->private);
2193 safe_free(nt_devmode);
2194 *devmode_ptr = NULL;
2197 /****************************************************************************
2198 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2199 ****************************************************************************/
2200 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2202 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2203 NT_PRINTER_PARAM *param_ptr;
2208 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2210 free_nt_devicemode(&info->devmode);
2212 for(param_ptr = info->specific; param_ptr; ) {
2213 NT_PRINTER_PARAM *tofree = param_ptr;
2215 param_ptr = param_ptr->next;
2216 free_nt_printer_param(&tofree);
2219 safe_free(*info_ptr);
2224 /****************************************************************************
2225 ****************************************************************************/
2226 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2230 NT_DEVICEMODE devmode;
2232 ZERO_STRUCT(devmode);
2234 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2236 if (!*nt_devmode) return len;
2238 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2242 &devmode.specversion,
2243 &devmode.driverversion,
2245 &devmode.driverextra,
2246 &devmode.orientation,
2248 &devmode.paperlength,
2249 &devmode.paperwidth,
2252 &devmode.defaultsource,
2253 &devmode.printquality,
2256 &devmode.yresolution,
2262 &devmode.bitsperpel,
2264 &devmode.pelsheight,
2265 &devmode.displayflags,
2266 &devmode.displayfrequency,
2270 &devmode.dithertype,
2273 &devmode.panningwidth,
2274 &devmode.panningheight,
2277 if (devmode.private) {
2278 /* the len in tdb_unpack is an int value and
2279 * devmode.driverextra is only a short
2281 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2282 devmode.driverextra=(uint16)extra_len;
2284 /* check to catch an invalid TDB entry so we don't segfault */
2285 if (devmode.driverextra == 0) {
2286 devmode.private = NULL;
2290 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2292 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2293 if (devmode.private)
2294 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2299 /****************************************************************************
2300 ****************************************************************************/
2301 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2304 NT_PRINTER_PARAM param, *p;
2309 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2312 len += tdb_unpack(buf+len, buflen-len, "fdB",
2318 *list = memdup(¶m, sizeof(param));
2320 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2326 static void map_to_os2_driver(fstring drivername)
2328 static BOOL initialised=False;
2329 static fstring last_from,last_to;
2330 char *mapfile = lp_os2_driver_map();
2331 char **lines = NULL;
2335 if (!strlen(drivername))
2342 *last_from = *last_to = 0;
2346 if (strequal(drivername,last_from)) {
2347 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2348 fstrcpy(drivername,last_to);
2352 lines = file_lines_load(mapfile, &numlines);
2353 if (numlines == 0) {
2354 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2358 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2360 for( i = 0; i < numlines; i++) {
2361 char *nt_name = lines[i];
2362 char *os2_name = strchr(nt_name,'=');
2369 while (isspace(*nt_name))
2372 if (!*nt_name || strchr("#;",*nt_name))
2376 int l = strlen(nt_name);
2377 while (l && isspace(nt_name[l-1])) {
2383 while (isspace(*os2_name))
2387 int l = strlen(os2_name);
2388 while (l && isspace(os2_name[l-1])) {
2394 if (strequal(nt_name,drivername)) {
2395 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2396 fstrcpy(last_from,drivername);
2397 fstrcpy(last_to,os2_name);
2398 fstrcpy(drivername,os2_name);
2399 file_lines_free(lines);
2404 file_lines_free(lines);
2407 /****************************************************************************
2408 get a default printer info 2 struct
2409 ****************************************************************************/
2410 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2412 extern pstring global_myname;
2414 NT_PRINTER_INFO_LEVEL_2 info;
2418 snum = lp_servicenumber(sharename);
2420 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2421 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2422 global_myname, sharename);
2423 fstrcpy(info.sharename, sharename);
2424 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2425 fstrcpy(info.drivername, lp_printerdriver(snum));
2428 if (!*info.drivername)
2429 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2431 /* by setting the driver name to an empty string, a local NT admin
2432 can now run the **local** APW to install a local printer driver
2433 for a Samba shared printer in 2.2. Without this, drivers **must** be
2434 installed on the Samba server for NT clients --jerry */
2435 if (!*info.drivername)
2436 fstrcpy(info.drivername, "");
2440 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2442 pstrcpy(info.comment, "");
2443 fstrcpy(info.printprocessor, "winprint");
2444 fstrcpy(info.datatype, "RAW");
2446 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2447 | PRINTER_ATTRIBUTE_LOCAL \
2448 | PRINTER_ATTRIBUTE_RAW_ONLY \
2449 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2451 info.starttime = 0; /* Minutes since 12:00am GMT */
2452 info.untiltime = 0; /* Minutes since 12:00am GMT */
2454 info.default_priority = 1;
2455 info.setuptime = (uint32)time(NULL);
2457 #if 1 /* JRA - NO NOT CHANGE ! */
2458 info.devmode = NULL;
2461 * We should not return a default devicemode, as this causes
2462 * Win2K to not send the correct one on PCL drivers. It needs to
2463 * see a null devicemode so it can then overwrite the devicemode
2464 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2466 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2470 /* This will get the current RPC talloc context, but we should be
2471 passing this as a parameter... fixme... JRA ! */
2473 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2476 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2478 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2487 free_nt_devicemode(&info.devmode);
2491 /****************************************************************************
2492 ****************************************************************************/
2493 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2496 NT_PRINTER_INFO_LEVEL_2 info;
2498 TDB_DATA kbuf, dbuf;
2499 fstring printername;
2503 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2506 kbuf.dsize = strlen(key)+1;
2508 dbuf = tdb_fetch(tdb_printers, kbuf);
2510 return get_a_printer_2_default(info_ptr, sharename);
2512 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2515 &info.default_priority,
2532 info.printprocessor,
2536 /* Samba has to have shared raw drivers. */
2537 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2539 /* Restore the stripped strings. */
2540 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2541 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2543 fstrcpy(info.printername, printername);
2545 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2546 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2548 /* This will get the current RPC talloc context, but we should be
2549 passing this as a parameter... fixme... JRA ! */
2551 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2553 /* Fix for OS/2 drivers. */
2555 if (get_remote_arch() == RA_OS2)
2556 map_to_os2_driver(info.drivername);
2558 safe_free(dbuf.dptr);
2559 *info_ptr=memdup(&info, sizeof(info));
2561 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2562 sharename, info.printername, info.drivername));
2568 /****************************************************************************
2569 debugging function, dump at level 6 the struct in the logs
2570 ****************************************************************************/
2571 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2574 NT_PRINTER_INFO_LEVEL_2 *info2;
2576 DEBUG(106,("Dumping printer at level [%d]\n", level));
2582 if (printer.info_2 == NULL)
2586 info2=printer.info_2;
2588 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2589 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2590 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2591 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2592 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2593 DEBUGADD(106,("status:[%d]\n", info2->status));
2594 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2595 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2596 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2597 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2598 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2600 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2601 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2602 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2603 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2604 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2605 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2606 DEBUGADD(106,("location:[%s]\n", info2->location));
2607 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2608 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2609 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2610 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2616 DEBUGADD(1,("Level not implemented\n"));
2624 /****************************************************************************
2625 Get the parameters we can substitute in an NT print job.
2626 ****************************************************************************/
2628 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2630 NT_PRINTER_INFO_LEVEL *printer = NULL;
2632 **printername = **sharename = **portname = '\0';
2634 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2637 fstrcpy(*printername, printer->info_2->printername);
2638 fstrcpy(*sharename, printer->info_2->sharename);
2639 fstrcpy(*portname, printer->info_2->portname);
2641 free_a_printer(&printer, 2);
2645 * The function below are the high level ones.
2646 * only those ones must be called from the spoolss code.
2650 /****************************************************************************
2651 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2652 ****************************************************************************/
2654 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2658 dump_a_printer(printer, level);
2664 printer.info_2->c_setprinter++;
2665 result=update_a_printer_2(printer.info_2);
2676 /****************************************************************************
2677 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2678 We split this out from mod_a_printer as it updates the id's and timestamps.
2679 ****************************************************************************/
2681 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2685 dump_a_printer(printer, level);
2692 * Update the changestamp.
2693 * Note we must *not* do this in mod_a_printer().
2696 time_t time_unix = time(NULL);
2697 unix_to_nt_time(&time_nt, time_unix);
2698 if (printer.info_2->changeid==time_nt.low)
2699 printer.info_2->changeid++;
2701 printer.info_2->changeid=time_nt.low;
2703 printer.info_2->c_setprinter++;
2705 result=update_a_printer_2(printer.info_2);
2716 /****************************************************************************
2717 Initialize printer devmode & data with previously saved driver init values.
2718 ****************************************************************************/
2719 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2723 TDB_DATA kbuf, dbuf;
2724 NT_PRINTER_PARAM *current;
2725 NT_PRINTER_INFO_LEVEL_2 info;
2729 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2732 kbuf.dsize = strlen(key)+1;
2734 dbuf = tdb_fetch(tdb_drivers, kbuf);
2739 * Get the saved DEVMODE..
2741 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2744 * The saved DEVMODE contains the devicename from the printer used during
2745 * the initialization save. Change it to reflect the new printer.
2747 ZERO_STRUCT(info.devmode->devicename);
2748 fstrcpy(info.devmode->devicename, info_ptr->printername);
2751 * Bind the saved DEVMODE to the new the printer.
2753 free_nt_devicemode(&info_ptr->devmode);
2754 info_ptr->devmode = info.devmode;
2756 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2757 info_ptr->printername, info_ptr->drivername));
2760 * There should not be any printer data 'specifics' already set during the
2761 * add printer operation, if there are delete them.
2763 while ( (current=info_ptr->specific) != NULL ) {
2764 info_ptr->specific=current->next;
2765 safe_free(current->data);
2770 * Add the printer data 'specifics' to the new printer
2772 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2774 safe_free(dbuf.dptr);
2779 /****************************************************************************
2780 Initialize printer devmode & data with previously saved driver init values.
2781 When a printer is created using AddPrinter, the drivername bound to the
2782 printer is used to lookup previously saved driver initialization info, which
2783 is bound to the new printer.
2784 ****************************************************************************/
2786 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2794 result=set_driver_init_2(printer->info_2);
2805 /****************************************************************************
2806 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2807 in the tdb. Note: this is different from the driver entry and the printer
2808 entry. There should be a single driver init entry for each driver regardless
2809 of whether it was installed from NT or 2K. Technically, they should be
2810 different, but they work out to the same struct.
2811 ****************************************************************************/
2812 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2816 int buflen, len, ret;
2817 TDB_DATA kbuf, dbuf;
2824 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2826 len += pack_specifics(info->specific, buf+len, buflen-len);
2828 if (buflen != len) {
2831 tb = (char *)Realloc(buf, len);
2833 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2842 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2845 kbuf.dsize = strlen(key)+1;
2849 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2853 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2857 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2858 info->sharename, info->drivername));
2863 /****************************************************************************
2864 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2865 ****************************************************************************/
2867 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2871 dump_a_printer(printer, level);
2877 result=update_driver_init_2(printer.info_2);
2888 /****************************************************************************
2889 Convert the printer data value, a REG_BINARY array, into an initialization
2890 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2891 got to keep the endians happy :).
2892 ****************************************************************************/
2894 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2896 BOOL result = False;
2900 ZERO_STRUCT(devmode);
2902 prs_init(&ps, 0, ctx, UNMARSHALL);
2903 ps.data_p = (char *)param->data;
2904 ps.buffer_size = param->data_len;
2906 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2907 result = convert_devicemode("", &devmode, &nt_devmode);
2909 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2914 /****************************************************************************
2915 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2917 1. Use the driver's config DLL to this UNC printername and:
2918 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2919 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2920 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2922 The last step triggers saving the "driver initialization" information for
2923 this printer into the tdb. Later, new printers that use this driver will
2924 have this initialization information bound to them. This simulates the
2925 driver initialization, as if it had run on the Samba server (as it would
2928 The Win32 client side code requirement sucks! But until we can run arbitrary
2929 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2931 It would have been easier to use SetPrinter because all the UNMARSHALLING of
2932 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2933 about it and you will realize why. JRR 010720
2934 ****************************************************************************/
2936 static uint32 save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2938 uint32 status = ERRsuccess;
2939 TALLOC_CTX *ctx = NULL;
2940 NT_DEVICEMODE *nt_devmode = NULL;
2941 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2944 * Set devmode on printer info, so entire printer initialization can be
2947 if ((ctx = talloc_init()) == NULL)
2950 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2955 ZERO_STRUCTP(nt_devmode);
2958 * The DEVMODE is held in the 'data' component of the param in raw binary.
2959 * Convert it to to a devmode structure
2961 if (!convert_driver_init(param, ctx, nt_devmode)) {
2962 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
2963 status = ERRinvalidparam;
2968 * Pack up and add (or update) the DEVMODE and any current printer data to
2969 * a 'driver init' element in the tdb
2972 printer->info_2->devmode = nt_devmode;
2973 if (update_driver_init(*printer, 2)!=0) {
2974 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
2980 * If driver initialization info was successfully saved, set the current
2981 * printer to match it. This allows initialization of the current printer
2982 * as well as the driver.
2984 if (mod_a_printer(*printer, 2)!=0) {
2985 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
2986 printer->info_2->printername));
2987 status = ERRinvalidparam;
2991 talloc_destroy(ctx);
2993 safe_free(nt_devmode->private);
2994 safe_free(nt_devmode);
2995 printer->info_2->devmode = tmp_devmode;
3000 /****************************************************************************
3001 Update the driver init info (DEVMODE and specifics) for a printer
3002 ****************************************************************************/
3004 uint32 save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3006 uint32 status = ERRsuccess;
3012 status=save_driver_init_2(printer, param);
3016 status=ERRunknownlevel;
3023 /****************************************************************************
3024 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3025 ****************************************************************************/
3027 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3030 NT_PRINTER_INFO_LEVEL *printer = NULL;
3034 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3040 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3041 DEBUG(0,("get_a_printer: malloc fail.\n"));
3044 ZERO_STRUCTP(printer);
3045 result=get_a_printer_2(&printer->info_2, sharename);
3047 dump_a_printer(*printer, level);
3048 *pp_printer = printer;
3059 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
3064 /****************************************************************************
3065 Deletes a NT_PRINTER_INFO_LEVEL struct.
3066 ****************************************************************************/
3068 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3071 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3073 DEBUG(104,("freeing a printer at level [%d]\n", level));
3075 if (printer == NULL)
3082 if (printer->info_2 != NULL)
3084 free_nt_printer_info_level_2(&printer->info_2);
3103 /****************************************************************************
3104 ****************************************************************************/
3105 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3108 DEBUG(104,("adding a printer at level [%d]\n", level));
3109 dump_a_printer_driver(driver, level);
3115 result=add_a_printer_driver_3(driver.info_3);
3121 result=add_a_printer_driver_6(driver.info_6);
3131 /****************************************************************************
3132 ****************************************************************************/
3133 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3134 fstring printername, fstring architecture, uint32 version)
3142 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3151 dump_a_printer_driver(*driver, level);
3155 /****************************************************************************
3156 ****************************************************************************/
3157 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3165 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3166 if (driver.info_3 != NULL)
3168 info3=driver.info_3;
3169 safe_free(info3->dependentfiles);
3170 ZERO_STRUCTP(info3);
3182 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3183 if (driver.info_6 != NULL)
3185 info6=driver.info_6;
3186 safe_free(info6->dependentfiles);
3187 safe_free(info6->previousnames);
3188 ZERO_STRUCTP(info6);
3206 /****************************************************************************
3207 Determine whether or not a particular driver is currently assigned
3209 ****************************************************************************/
3210 BOOL printer_driver_in_use (char *arch, char *driver)
3212 TDB_DATA kbuf, newkey, dbuf;
3213 NT_PRINTER_INFO_LEVEL_2 info;
3217 if (!nt_printing_init())
3220 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3222 /* loop through the printers.tdb and check for the drivername */
3223 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3224 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3227 dbuf = tdb_fetch(tdb_printers, kbuf);
3231 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3234 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3237 &info.default_priority,
3254 info.printprocessor,
3258 safe_free(dbuf.dptr);
3261 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3266 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3267 info.printername, info.drivername));
3269 if (strcmp(info.drivername, driver) == 0)
3271 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3272 info.printername, driver));
3276 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3280 /* report that the driver is in use by default */
3284 /****************************************************************************
3285 Remove a printer driver from the TDB. This assumes that the the driver was
3286 previously looked up.
3287 ***************************************************************************/
3288 uint32 delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3295 get_short_archi(arch, i->environment);
3296 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3297 arch, i->cversion, i->name);
3298 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3301 kbuf.dsize=strlen(key)+1;
3303 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3304 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3305 return NT_STATUS_ACCESS_VIOLATION;
3308 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3311 return NT_STATUS_NOPROBLEMO;
3313 /****************************************************************************
3314 ****************************************************************************/
3315 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3316 fstring value, uint8 **data, uint32 *type, uint32 *len)
3318 /* right now that's enough ! */
3319 NT_PRINTER_PARAM *param;
3322 param=printer.info_2->specific;
3324 while (param != NULL && i < param_index) {
3332 /* exited because it exist */
3334 StrnCpy(value, param->value, sizeof(fstring)-1);
3335 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3338 ZERO_STRUCTP(*data);
3339 memcpy(*data, param->data, param->data_len);
3340 *len=param->data_len;
3344 /****************************************************************************
3345 ****************************************************************************/
3346 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3347 fstring value, uint8 **data, uint32 *type, uint32 *len)
3349 /* right now that's enough ! */
3350 NT_PRINTER_PARAM *param;
3352 DEBUG(10, ("get_specific_param\n"));
3354 param=printer.info_2->specific;
3356 while (param != NULL)
3358 #if 1 /* JRA - I think this should be case insensitive.... */
3359 if ( strequal(value, param->value)
3361 if ( !strcmp(value, param->value)
3363 && strlen(value)==strlen(param->value))
3371 DEBUGADD(10, ("get_specific_param: found one param\n"));
3372 /* exited because it exist */
3375 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3378 memcpy(*data, param->data, param->data_len);
3379 *len=param->data_len;
3381 DEBUGADD(10, ("get_specific_param: exit true\n"));
3384 DEBUGADD(10, ("get_specific_param: exit false\n"));
3388 /****************************************************************************
3389 Store a security desc for a printer.
3390 ****************************************************************************/
3392 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3394 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3395 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3397 TALLOC_CTX *mem_ctx = NULL;
3401 mem_ctx = talloc_init();
3402 if (mem_ctx == NULL)
3405 /* The old owner and group sids of the security descriptor are not
3406 present when new ACEs are added or removed by changing printer
3407 permissions through NT. If they are NULL in the new security
3408 descriptor then copy them over from the old one. */
3410 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3411 DOM_SID *owner_sid, *group_sid;
3412 SEC_ACL *dacl, *sacl;
3413 SEC_DESC *psd = NULL;
3416 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3418 /* Pick out correct owner and group sids */
3420 owner_sid = secdesc_ctr->sec->owner_sid ?
3421 secdesc_ctr->sec->owner_sid :
3422 old_secdesc_ctr->sec->owner_sid;
3424 group_sid = secdesc_ctr->sec->grp_sid ?
3425 secdesc_ctr->sec->grp_sid :
3426 old_secdesc_ctr->sec->grp_sid;
3428 dacl = secdesc_ctr->sec->dacl ?
3429 secdesc_ctr->sec->dacl :
3430 old_secdesc_ctr->sec->dacl;
3432 sacl = secdesc_ctr->sec->sacl ?
3433 secdesc_ctr->sec->sacl :
3434 old_secdesc_ctr->sec->sacl;
3436 /* Make a deep copy of the security descriptor */
3438 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3439 owner_sid, group_sid,
3444 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3447 if (!new_secdesc_ctr) {
3448 new_secdesc_ctr = secdesc_ctr;
3451 /* Store the security descriptor in a tdb */
3453 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3454 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3456 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3458 status = ERRbadfunc;
3462 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3464 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3467 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3468 status = ERRbadfunc;
3471 /* Free malloc'ed memory */
3477 talloc_destroy(mem_ctx);
3481 /****************************************************************************
3482 Construct a default security descriptor buffer for a printer.
3483 ****************************************************************************/
3485 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3489 SEC_ACL *psa = NULL;
3490 SEC_DESC_BUF *sdb = NULL;
3491 SEC_DESC *psd = NULL;
3494 enum SID_NAME_USE name_type;
3496 /* Create an ACE where Everyone is allowed to print */
3498 init_sec_access(&sa, PRINTER_ACE_PRINT);
3499 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3500 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3502 /* Make the security descriptor owned by the Administrators group
3503 on the PDC of the domain. */
3505 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3506 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3510 /* Backup plan - make printer owned by admins or root.
3511 This should emulate a lanman printer as security
3512 settings can't be changed. */
3514 sid_peek_rid(&owner_sid, &owner_rid);
3516 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3517 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3518 owner_rid != DOMAIN_USER_RID_ADMIN &&
3519 !lookup_name("root", &owner_sid, &name_type)) {
3520 sid_copy(&owner_sid, &global_sid_World);
3524 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3525 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3526 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3527 SEC_ACE_FLAG_INHERIT_ONLY);
3529 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3530 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3531 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3533 /* The ACL revision number in rpc_secdesc.h differs from the one
3534 created by NT when setting ACE entries in printer
3535 descriptors. NT4 complains about the property being edited by a
3538 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3539 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3541 NULL, psa, &sd_size);
3545 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3549 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3551 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3552 (unsigned int)sd_size));
3557 /****************************************************************************
3558 Get a security desc for a printer.
3559 ****************************************************************************/
3561 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3567 if ((temp = strchr(printername + 2, '\\'))) {
3568 printername = temp + 1;
3571 /* Fetch security descriptor from tdb */
3573 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3575 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3576 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3578 DEBUG(4,("using default secdesc for %s\n", printername));
3580 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3587 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3588 this security descriptor has been created when winbindd was
3589 down. Take ownership of security descriptor. */
3591 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3593 enum SID_NAME_USE name_type;
3595 /* Change sd owner to workgroup administrator */
3597 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3599 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3600 SEC_DESC *psd = NULL;
3605 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3607 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3609 (*secdesc_ctr)->sec->grp_sid,
3610 (*secdesc_ctr)->sec->sacl,
3611 (*secdesc_ctr)->sec->dacl,
3614 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3616 /* Swap with other one */
3618 *secdesc_ctr = new_secdesc_ctr;
3622 nt_printing_setsec(printername, *secdesc_ctr);
3626 if (DEBUGLEVEL >= 10) {
3627 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3630 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3631 printername, the_acl->num_aces));
3633 for (i = 0; i < the_acl->num_aces; i++) {
3636 sid_to_string(sid_str, &the_acl->ace[i].sid);
3638 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3639 the_acl->ace[i].type, the_acl->ace[i].flags,
3640 the_acl->ace[i].info.mask));
3650 1: level not implemented
3651 2: file doesn't exist
3652 3: can't allocate memory
3653 4: can't free memory
3654 5: non existant struct
3658 A printer and a printer driver are 2 different things.
3659 NT manages them separatelly, Samba does the same.
3660 Why ? Simply because it's easier and it makes sense !
3662 Now explanation: You have 3 printers behind your samba server,
3663 2 of them are the same make and model (laser A and B). But laser B
3664 has an 3000 sheet feeder and laser A doesn't such an option.
3665 Your third printer is an old dot-matrix model for the accounting :-).
3667 If the /usr/local/samba/lib directory (default dir), you will have
3668 5 files to describe all of this.
3670 3 files for the printers (1 by printer):
3673 NTprinter_accounting
3674 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3675 NTdriver_printer model X
3676 NTdriver_printer model Y
3678 jfm: I should use this comment for the text file to explain
3679 same thing for the forms BTW.
3680 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3684 /* Convert generic access rights to printer object specific access rights.
3685 It turns out that NT4 security descriptors use generic access rights and
3686 NT5 the object specific ones. */
3688 void map_printer_permissions(SEC_DESC *sd)
3692 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3693 se_map_generic(&sd->dacl->ace[i].info.mask,
3694 &printer_generic_mapping);
3698 /****************************************************************************
3699 Check a user has permissions to perform the given operation. We use the
3700 permission constants defined in include/rpc_spoolss.h to check the various
3701 actions we perform when checking printer access.
3703 PRINTER_ACCESS_ADMINISTER:
3704 print_queue_pause, print_queue_resume, update_printer_sec,
3705 update_printer, spoolss_addprinterex_level_2,
3706 _spoolss_setprinterdata
3711 JOB_ACCESS_ADMINISTER:
3712 print_job_delete, print_job_pause, print_job_resume,
3715 ****************************************************************************/
3716 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3718 SEC_DESC_BUF *secdesc = NULL;
3719 uint32 access_granted, status;
3722 TALLOC_CTX *mem_ctx = NULL;
3723 extern struct current_user current_user;
3725 /* If user is NULL then use the current_user structure */
3727 if (!user) user = ¤t_user;
3729 /* Always allow root or printer admins to do anything */
3731 if (user->uid == 0 ||
3732 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3736 /* Get printer name */
3738 pname = PRINTERNAME(snum);
3740 if (!pname || !*pname) {
3745 /* Get printer security descriptor */
3747 if(!(mem_ctx = talloc_init())) {
3752 nt_printing_getsec(mem_ctx, pname, &secdesc);
3754 if (access_type == JOB_ACCESS_ADMINISTER) {
3755 SEC_DESC_BUF *parent_secdesc = secdesc;
3757 /* Create a child security descriptor to check permissions
3758 against. This is because print jobs are child objects
3759 objects of a printer. */
3761 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3763 /* Now this is the bit that really confuses me. The access
3764 type needs to be changed from JOB_ACCESS_ADMINISTER to
3765 PRINTER_ACCESS_ADMINISTER for this to work. Something
3766 to do with the child (job) object becoming like a
3769 access_type = PRINTER_ACCESS_ADMINISTER;
3774 map_printer_permissions(secdesc->sec);
3776 result = se_access_check(secdesc->sec, user, access_type,
3777 &access_granted, &status);
3779 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3781 talloc_destroy(mem_ctx);
3789 /****************************************************************************
3790 Check the time parameters allow a print operation.
3791 *****************************************************************************/
3793 BOOL print_time_access_check(int snum)
3795 NT_PRINTER_INFO_LEVEL *printer = NULL;
3797 time_t now = time(NULL);
3801 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3804 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3808 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3810 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3813 free_a_printer(&printer, 2);
3821 /****************************************************************************
3822 Attempt to write a default device.
3823 *****************************************************************************/
3825 uint32 printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3827 NT_PRINTER_INFO_LEVEL *printer = NULL;
3832 * Don't bother if no default devicemode was sent.
3835 if (printer_default->devmode_cont.devmode == NULL)
3838 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3842 * Just ignore it if we already have a devmode.
3845 if (printer->info_2->devmode != NULL)
3849 * We don't have a devicemode and we're trying to write
3850 * one. Check we have the access needed.
3852 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3854 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3855 PRINTER_ACCESS_ADMINISTER) {
3856 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3857 result = ERRnoaccess;
3861 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3862 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3863 lp_servicename(snum) ));
3864 result = ERRnoaccess;
3865 /*result = NT_STATUS_NO_PROBLEMO;*/
3869 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3872 * Convert the on the wire devicemode format to the internal one.
3875 if (!convert_devicemode(printer->info_2->printername,
3876 printer_default->devmode_cont.devmode,
3877 &printer->info_2->devmode)) {
3883 * Finally write back to the tdb.
3886 if (add_a_printer(*printer, 2)!=0) {
3887 result = ERRnoaccess;
3893 free_a_printer(&printer, 2);