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, TDB_DEFAULT, 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, TDB_DEFAULT, 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, TDB_DEFAULT, 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, WERROR *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 = WERR_INVALID_PARAM;
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, WERROR *perr)
932 files_struct *fsp = NULL;
935 connection_struct *conn;
939 /* If architecture is Windows 95/98/ME, the version is always 0. */
940 if (strcmp(architecture, "WIN40") == 0) {
941 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
945 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
946 /* Null password is ok - we are already an authenticated user... */
948 conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status);
951 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
952 *perr = ntstatus_to_werror(nt_status);
956 /* Save who we are - we are temporarily becoming the connection user. */
959 if (!become_user(conn, conn->vuid)) {
960 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
961 *perr = WERR_ACCESS_DENIED;
966 /* Open the driver file (Portable Executable format) and determine the
967 * deriver the cversion. */
968 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
970 unix_convert(driverpath,conn,NULL,&bad_path,&st);
972 fsp = open_file_shared(conn, driverpath, &st,
973 SET_OPEN_MODE(DOS_OPEN_RDONLY),
974 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
975 0, 0, &access_mode, &action);
977 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
979 *perr = WERR_ACCESS_DENIED;
985 int ret = get_file_version(fsp, driverpath, &major, &minor);
986 if (ret == -1) goto error_exit;
989 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
994 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
995 * for more details. Version in this case is not just the version of the
996 * file, but the version in the sense of kernal mode (2) vs. user mode
997 * (3) drivers. Other bits of the version fields are the version info.
1000 cversion = major & 0x0000ffff;
1002 case 2: /* WinNT drivers */
1003 case 3: /* Win2K drivers */
1007 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1008 driverpath, cversion));
1012 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1013 driverpath, major, minor));
1016 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1017 driverpath, cversion));
1019 close_file(fsp, True);
1020 close_cnum(conn, user->vuid);
1027 close_file(fsp, True);
1029 close_cnum(conn, user->vuid);
1034 /****************************************************************************
1035 ****************************************************************************/
1036 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1037 struct current_user *user)
1039 fstring architecture;
1045 /* clean up the driver name.
1046 * we can get .\driver.dll
1047 * or worse c:\windows\system\driver.dll !
1049 /* using an intermediate string to not have overlaping memcpy()'s */
1050 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1051 fstrcpy(new_name, p+1);
1052 fstrcpy(driver->driverpath, new_name);
1055 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1056 fstrcpy(new_name, p+1);
1057 fstrcpy(driver->datafile, new_name);
1060 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1061 fstrcpy(new_name, p+1);
1062 fstrcpy(driver->configfile, new_name);
1065 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1066 fstrcpy(new_name, p+1);
1067 fstrcpy(driver->helpfile, new_name);
1070 if (driver->dependentfiles) {
1071 for (i=0; *driver->dependentfiles[i]; i++) {
1072 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1073 fstrcpy(new_name, p+1);
1074 fstrcpy(driver->dependentfiles[i], new_name);
1079 get_short_archi(architecture, driver->environment);
1081 /* jfm:7/16/2000 the client always sends the cversion=0.
1082 * The server should check which version the driver is by reading
1083 * the PE header of driver->driverpath.
1085 * For Windows 95/98 the version is 0 (so the value sent is correct)
1086 * For Windows NT (the architecture doesn't matter)
1087 * NT 3.1: cversion=0
1088 * NT 3.5/3.51: cversion=1
1092 if ((driver->cversion = get_correct_cversion( architecture,
1093 driver->driverpath, user, &err)) == -1)
1099 /****************************************************************************
1100 ****************************************************************************/
1101 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1102 struct current_user *user)
1104 fstring architecture;
1110 /* clean up the driver name.
1111 * we can get .\driver.dll
1112 * or worse c:\windows\system\driver.dll !
1114 /* using an intermediate string to not have overlaping memcpy()'s */
1115 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1116 fstrcpy(new_name, p+1);
1117 fstrcpy(driver->driverpath, new_name);
1120 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1121 fstrcpy(new_name, p+1);
1122 fstrcpy(driver->datafile, new_name);
1125 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1126 fstrcpy(new_name, p+1);
1127 fstrcpy(driver->configfile, new_name);
1130 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1131 fstrcpy(new_name, p+1);
1132 fstrcpy(driver->helpfile, new_name);
1135 if (driver->dependentfiles) {
1136 for (i=0; *driver->dependentfiles[i]; i++) {
1137 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1138 fstrcpy(new_name, p+1);
1139 fstrcpy(driver->dependentfiles[i], new_name);
1144 get_short_archi(architecture, driver->environment);
1146 /* jfm:7/16/2000 the client always sends the cversion=0.
1147 * The server should check which version the driver is by reading
1148 * the PE header of driver->driverpath.
1150 * For Windows 95/98 the version is 0 (so the value sent is correct)
1151 * For Windows NT (the architecture doesn't matter)
1152 * NT 3.1: cversion=0
1153 * NT 3.5/3.51: cversion=1
1157 if ((driver->version = get_correct_cversion(architecture,
1158 driver->driverpath, user, &err)) == -1)
1164 /****************************************************************************
1165 ****************************************************************************/
1166 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1167 uint32 level, struct current_user *user)
1172 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1173 driver=driver_abstract.info_3;
1174 return clean_up_driver_struct_level_3(driver, user);
1178 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1179 driver=driver_abstract.info_6;
1180 return clean_up_driver_struct_level_6(driver, user);
1183 return WERR_INVALID_PARAM;
1187 /****************************************************************************
1188 This function sucks and should be replaced. JRA.
1189 ****************************************************************************/
1191 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1193 dst->cversion = src->version;
1195 fstrcpy( dst->name, src->name);
1196 fstrcpy( dst->environment, src->environment);
1197 fstrcpy( dst->driverpath, src->driverpath);
1198 fstrcpy( dst->datafile, src->datafile);
1199 fstrcpy( dst->configfile, src->configfile);
1200 fstrcpy( dst->helpfile, src->helpfile);
1201 fstrcpy( dst->monitorname, src->monitorname);
1202 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1203 dst->dependentfiles = src->dependentfiles;
1206 #if 0 /* Debugging function */
1208 static char* ffmt(unsigned char *c){
1210 static char ffmt_str[17];
1212 for (i=0; i<16; i++) {
1213 if ((c[i] < ' ') || (c[i] > '~'))
1224 /****************************************************************************
1225 ****************************************************************************/
1226 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1227 struct current_user *user, WERROR *perr)
1229 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1230 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1231 fstring architecture;
1236 connection_struct *conn;
1244 driver=driver_abstract.info_3;
1245 else if (level==6) {
1246 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1247 driver = &converted_driver;
1249 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1253 get_short_archi(architecture, driver->environment);
1255 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1256 /* Null password is ok - we are already an authenticated user... */
1258 conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status);
1261 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1262 *perr = ntstatus_to_werror(nt_status);
1267 * Save who we are - we are temporarily becoming the connection user.
1272 if (!become_user(conn, conn->vuid)) {
1273 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1279 * make the directories version and version\driver_name
1280 * under the architecture directory.
1282 DEBUG(5,("Creating first directory\n"));
1283 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1284 mkdir_internal(conn, new_dir);
1286 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1287 * listed for this driver which has already been moved, skip it (note:
1288 * drivers may list the same file name several times. Then check if the
1289 * file already exists in archi\cversion\, if so, check that the version
1290 * info (or time stamps if version info is unavailable) is newer (or the
1291 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1292 * Otherwise, delete the file.
1294 * If a file is not moved to archi\cversion\ because of an error, all the
1295 * rest of the 'unmoved' driver files are removed from archi\. If one or
1296 * more of the driver's files was already moved to archi\cversion\, it
1297 * potentially leaves the driver in a partially updated state. Version
1298 * trauma will most likely occur if an client attempts to use any printer
1299 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1300 * done is appropriate... later JRR
1303 DEBUG(5,("Moving files now !\n"));
1305 if (driver->driverpath && strlen(driver->driverpath)) {
1306 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1307 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1308 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1310 status = rename_internals(conn, new_name, old_name, True);
1311 if (!NT_STATUS_IS_OK(status)) {
1312 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1313 new_name, old_name));
1314 *perr = ntstatus_to_werror(status);
1315 unlink_internals(conn, 0, new_name);
1320 unlink_internals(conn, 0, new_name);
1323 if (driver->datafile && strlen(driver->datafile)) {
1324 if (!strequal(driver->datafile, driver->driverpath)) {
1325 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1326 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1327 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1329 status = rename_internals(conn, new_name, old_name, True);
1330 if (!NT_STATUS_IS_OK(status)) {
1331 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1332 new_name, old_name));
1333 *perr = ntstatus_to_werror(status);
1334 unlink_internals(conn, 0, new_name);
1339 unlink_internals(conn, 0, new_name);
1343 if (driver->configfile && strlen(driver->configfile)) {
1344 if (!strequal(driver->configfile, driver->driverpath) &&
1345 !strequal(driver->configfile, driver->datafile)) {
1346 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1347 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1348 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1350 status = rename_internals(conn, new_name, old_name, True);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1353 new_name, old_name));
1354 *perr = ntstatus_to_werror(status);
1355 unlink_internals(conn, 0, new_name);
1360 unlink_internals(conn, 0, new_name);
1364 if (driver->helpfile && strlen(driver->helpfile)) {
1365 if (!strequal(driver->helpfile, driver->driverpath) &&
1366 !strequal(driver->helpfile, driver->datafile) &&
1367 !strequal(driver->helpfile, driver->configfile)) {
1368 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1369 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1370 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1372 status = rename_internals(conn, new_name, old_name, True);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1375 new_name, old_name));
1376 *perr = ntstatus_to_werror(status);
1377 unlink_internals(conn, 0, new_name);
1382 unlink_internals(conn, 0, new_name);
1386 if (driver->dependentfiles) {
1387 for (i=0; *driver->dependentfiles[i]; i++) {
1388 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1389 !strequal(driver->dependentfiles[i], driver->datafile) &&
1390 !strequal(driver->dependentfiles[i], driver->configfile) &&
1391 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1393 for (j=0; j < i; j++) {
1394 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1399 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1400 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1401 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1403 status = rename_internals(conn, new_name, old_name, True);
1404 if (!NT_STATUS_IS_OK(status)) {
1405 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1406 new_name, old_name));
1407 *perr = ntstatus_to_werror(status);
1408 unlink_internals(conn, 0, new_name);
1413 unlink_internals(conn, 0, new_name);
1419 close_cnum(conn, user->vuid);
1422 return ver == -1 ? False : True;
1425 /****************************************************************************
1426 ****************************************************************************/
1427 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1430 fstring architecture;
1436 TDB_DATA kbuf, dbuf;
1438 get_short_archi(architecture, driver->environment);
1440 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1441 * \\server is added in the rpc server layer.
1442 * It does make sense to NOT store the server's name in the printer TDB.
1445 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1447 /* .inf files do not always list a file for each of the four standard files.
1448 * Don't prepend a path to a null filename, or client claims:
1449 * "The server on which the printer resides does not have a suitable
1450 * <printer driver name> printer driver installed. Click OK if you
1451 * wish to install the driver on your local machine."
1453 if (strlen(driver->driverpath)) {
1454 fstrcpy(temp_name, driver->driverpath);
1455 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1458 if (strlen(driver->datafile)) {
1459 fstrcpy(temp_name, driver->datafile);
1460 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1463 if (strlen(driver->configfile)) {
1464 fstrcpy(temp_name, driver->configfile);
1465 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1468 if (strlen(driver->helpfile)) {
1469 fstrcpy(temp_name, driver->helpfile);
1470 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1473 if (driver->dependentfiles) {
1474 for (i=0; *driver->dependentfiles[i]; i++) {
1475 fstrcpy(temp_name, driver->dependentfiles[i]);
1476 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1480 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1482 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1489 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1492 driver->environment,
1497 driver->monitorname,
1498 driver->defaultdatatype);
1500 if (driver->dependentfiles) {
1501 for (i=0; *driver->dependentfiles[i]; i++) {
1502 len += tdb_pack(buf+len, buflen-len, "f",
1503 driver->dependentfiles[i]);
1507 if (len != buflen) {
1510 tb = (char *)Realloc(buf, len);
1512 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1523 kbuf.dsize = strlen(key)+1;
1527 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1531 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1537 /****************************************************************************
1538 ****************************************************************************/
1539 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1541 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1544 info3.cversion = driver->version;
1545 fstrcpy(info3.name,driver->name);
1546 fstrcpy(info3.environment,driver->environment);
1547 fstrcpy(info3.driverpath,driver->driverpath);
1548 fstrcpy(info3.datafile,driver->datafile);
1549 fstrcpy(info3.configfile,driver->configfile);
1550 fstrcpy(info3.helpfile,driver->helpfile);
1551 fstrcpy(info3.monitorname,driver->monitorname);
1552 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1553 info3.dependentfiles = driver->dependentfiles;
1555 return add_a_printer_driver_3(&info3);
1559 /****************************************************************************
1560 ****************************************************************************/
1561 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1563 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1567 fstrcpy(info.name, in_prt);
1568 fstrcpy(info.defaultdatatype, "RAW");
1570 fstrcpy(info.driverpath, "");
1571 fstrcpy(info.datafile, "");
1572 fstrcpy(info.configfile, "");
1573 fstrcpy(info.helpfile, "");
1575 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1578 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1579 fstrcpy(info.dependentfiles[0], "");
1581 *info_ptr = memdup(&info, sizeof(info));
1586 /****************************************************************************
1587 ****************************************************************************/
1588 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1590 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1591 TDB_DATA kbuf, dbuf;
1592 fstring architecture;
1597 ZERO_STRUCT(driver);
1599 get_short_archi(architecture, in_arch);
1601 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1603 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1606 kbuf.dsize = strlen(key)+1;
1608 dbuf = tdb_fetch(tdb_drivers, kbuf);
1610 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1612 if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1614 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1623 driver.defaultdatatype);
1626 while (len < dbuf.dsize) {
1629 tddfs = (fstring *)Realloc(driver.dependentfiles,
1630 sizeof(fstring)*(i+2));
1631 if (tddfs == NULL) {
1632 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1635 else driver.dependentfiles = tddfs;
1637 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1638 &driver.dependentfiles[i]);
1641 if (driver.dependentfiles != NULL)
1642 fstrcpy(driver.dependentfiles[i], "");
1644 SAFE_FREE(dbuf.dptr);
1646 if (len != dbuf.dsize) {
1647 SAFE_FREE(driver.dependentfiles);
1649 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1652 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1657 /****************************************************************************
1658 ****************************************************************************/
1659 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1661 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1667 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1668 DEBUG(10,("driver key: [%s]\n", key));
1671 kbuf.dsize = strlen(key)+1;
1672 if (!tdb_exists(tdb_drivers, kbuf)) return False;
1675 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1677 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1678 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1679 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1680 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1681 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1682 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1683 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1685 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1686 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1687 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1689 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1690 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1691 pstrcat(line, info3->configfile);
1693 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1694 pstrcat(line, info3->datafile);
1696 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1697 pstrcat(line, info3->helpfile);
1699 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1700 pstrcat(line, info3->monitorname);
1702 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1705 for (i=0; info3->dependentfiles &&
1706 *info3->dependentfiles[i]; i++) {
1707 if (i) pstrcat(line, ","); /* don't end in a "," */
1708 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1709 pstrcat(line, info3->dependentfiles[i]);
1717 /****************************************************************************
1718 debugging function, dump at level 6 the struct in the logs
1719 ****************************************************************************/
1720 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1723 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1726 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1732 if (driver.info_3 == NULL)
1735 info3=driver.info_3;
1737 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1738 DEBUGADD(106,("name:[%s]\n", info3->name));
1739 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1740 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1741 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1742 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1743 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1744 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1745 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1747 for (i=0; info3->dependentfiles &&
1748 *info3->dependentfiles[i]; i++) {
1749 DEBUGADD(106,("dependentfile:[%s]\n",
1750 info3->dependentfiles[i]));
1757 DEBUGADD(1,("Level not implemented\n"));
1765 /****************************************************************************
1766 ****************************************************************************/
1767 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1771 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1773 if (!nt_devmode) return len;
1775 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1776 nt_devmode->devicename,
1777 nt_devmode->formname,
1779 nt_devmode->specversion,
1780 nt_devmode->driverversion,
1782 nt_devmode->driverextra,
1783 nt_devmode->orientation,
1784 nt_devmode->papersize,
1785 nt_devmode->paperlength,
1786 nt_devmode->paperwidth,
1789 nt_devmode->defaultsource,
1790 nt_devmode->printquality,
1793 nt_devmode->yresolution,
1794 nt_devmode->ttoption,
1795 nt_devmode->collate,
1796 nt_devmode->logpixels,
1799 nt_devmode->bitsperpel,
1800 nt_devmode->pelswidth,
1801 nt_devmode->pelsheight,
1802 nt_devmode->displayflags,
1803 nt_devmode->displayfrequency,
1804 nt_devmode->icmmethod,
1805 nt_devmode->icmintent,
1806 nt_devmode->mediatype,
1807 nt_devmode->dithertype,
1808 nt_devmode->reserved1,
1809 nt_devmode->reserved2,
1810 nt_devmode->panningwidth,
1811 nt_devmode->panningheight,
1812 nt_devmode->private);
1815 if (nt_devmode->private) {
1816 len += tdb_pack(buf+len, buflen-len, "B",
1817 nt_devmode->driverextra,
1818 nt_devmode->private);
1821 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1826 /****************************************************************************
1827 ****************************************************************************/
1828 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1832 while (param != NULL) {
1833 len += tdb_pack(buf+len, buflen-len, "pfdB",
1842 len += tdb_pack(buf+len, buflen-len, "p", param);
1848 /****************************************************************************
1849 delete a printer - this just deletes the printer info file, any open
1850 handles are not affected
1851 ****************************************************************************/
1852 uint32 del_a_printer(char *sharename)
1857 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1860 kbuf.dsize=strlen(key)+1;
1862 tdb_delete(tdb_printers, kbuf);
1866 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1867 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1868 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1869 /****************************************************************************
1870 ****************************************************************************/
1871 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1877 TDB_DATA kbuf, dbuf;
1880 * in addprinter: no servername and the printer is the name
1881 * in setprinter: servername is \\server
1882 * and printer is \\server\\printer
1884 * Samba manages only local printers.
1885 * we currently don't support things like path=\\other_server\printer
1888 if (info->servername[0]!='\0') {
1889 trim_string(info->printername, info->servername, NULL);
1890 trim_string(info->printername, "\\", NULL);
1891 info->servername[0]='\0';
1895 * JFM: one day I'll forget.
1896 * below that's info->portname because that's the SAMBA sharename
1897 * and I made NT 'thinks' it's the portname
1898 * the info->sharename is the thing you can name when you add a printer
1899 * that's the short-name when you create shared printer for 95/98
1900 * So I've made a limitation in SAMBA: you can only have 1 printer model
1901 * behind a SAMBA share.
1909 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1912 info->default_priority,
1929 info->printprocessor,
1933 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1935 len += pack_specifics(info->specific, buf+len, buflen-len);
1937 if (buflen != len) {
1940 tb = (char *)Realloc(buf, len);
1942 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1952 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1955 kbuf.dsize = strlen(key)+1;
1959 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
1962 if (!W_ERROR_IS_OK(ret))
1963 DEBUG(8, ("error updating printer to tdb on disk\n"));
1967 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1968 info->sharename, info->drivername, info->portname, len));
1974 /****************************************************************************
1975 ****************************************************************************/
1976 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1978 NT_PRINTER_PARAM *current;
1980 DEBUG(108,("add_a_specific_param\n"));
1982 (*param)->next=NULL;
1984 if (info_2->specific == NULL)
1986 info_2->specific=*param;
1990 current=info_2->specific;
1991 while (current->next != NULL) {
1992 current=current->next;
1994 current->next=*param;
2000 /****************************************************************************
2001 ****************************************************************************/
2002 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2004 NT_PRINTER_PARAM *current;
2005 NT_PRINTER_PARAM *previous;
2007 current=info_2->specific;
2010 if (current==NULL) return (False);
2012 if ( !strcmp(current->value, param->value) &&
2013 (strlen(current->value)==strlen(param->value)) ) {
2014 DEBUG(109,("deleting first value\n"));
2015 info_2->specific=current->next;
2016 SAFE_FREE(current->data);
2018 DEBUG(109,("deleted first value\n"));
2022 current=previous->next;
2024 while ( current!=NULL ) {
2025 if (!strcmp(current->value, param->value) &&
2026 strlen(current->value)==strlen(param->value) ) {
2027 DEBUG(109,("deleting current value\n"));
2028 previous->next=current->next;
2029 SAFE_FREE(current->data);
2031 DEBUG(109,("deleted current value\n"));
2035 previous=previous->next;
2036 current=current->next;
2041 /****************************************************************************
2042 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2043 ****************************************************************************/
2044 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2046 NT_PRINTER_PARAM *param = *param_ptr;
2051 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2053 SAFE_FREE(param->data);
2054 SAFE_FREE(*param_ptr);
2057 /****************************************************************************
2058 Malloc and return an NT devicemode.
2059 ****************************************************************************/
2061 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2064 * should I init this ones ???
2065 nt_devmode->devicename
2069 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2071 if (nt_devmode == NULL) {
2072 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2076 ZERO_STRUCTP(nt_devmode);
2078 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2079 fstrcpy(nt_devmode->devicename, adevice);
2081 fstrcpy(nt_devmode->formname, "Letter");
2083 nt_devmode->specversion = 0x0401;
2084 nt_devmode->driverversion = 0x0400;
2085 nt_devmode->size = 0x00DC;
2086 nt_devmode->driverextra = 0x0000;
2087 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2088 DEFAULTSOURCE | COPIES | SCALE |
2089 PAPERSIZE | ORIENTATION;
2090 nt_devmode->orientation = 1;
2091 nt_devmode->papersize = PAPER_LETTER;
2092 nt_devmode->paperlength = 0;
2093 nt_devmode->paperwidth = 0;
2094 nt_devmode->scale = 0x64;
2095 nt_devmode->copies = 01;
2096 nt_devmode->defaultsource = BIN_FORMSOURCE;
2097 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2098 nt_devmode->color = COLOR_MONOCHROME;
2099 nt_devmode->duplex = DUP_SIMPLEX;
2100 nt_devmode->yresolution = 0;
2101 nt_devmode->ttoption = TT_SUBDEV;
2102 nt_devmode->collate = COLLATE_FALSE;
2103 nt_devmode->icmmethod = 0;
2104 nt_devmode->icmintent = 0;
2105 nt_devmode->mediatype = 0;
2106 nt_devmode->dithertype = 0;
2108 /* non utilisés par un driver d'imprimante */
2109 nt_devmode->logpixels = 0;
2110 nt_devmode->bitsperpel = 0;
2111 nt_devmode->pelswidth = 0;
2112 nt_devmode->pelsheight = 0;
2113 nt_devmode->displayflags = 0;
2114 nt_devmode->displayfrequency = 0;
2115 nt_devmode->reserved1 = 0;
2116 nt_devmode->reserved2 = 0;
2117 nt_devmode->panningwidth = 0;
2118 nt_devmode->panningheight = 0;
2120 nt_devmode->private = NULL;
2124 /****************************************************************************
2125 Deepcopy an NT devicemode.
2126 ****************************************************************************/
2128 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2130 NT_DEVICEMODE *new_nt_devicemode = NULL;
2132 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2133 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2137 new_nt_devicemode->private = NULL;
2138 if (nt_devicemode->private != NULL) {
2139 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2140 SAFE_FREE(new_nt_devicemode);
2141 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2146 return new_nt_devicemode;
2149 /****************************************************************************
2150 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2151 ****************************************************************************/
2153 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2155 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2157 if(nt_devmode == NULL)
2160 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2162 SAFE_FREE(nt_devmode->private);
2163 SAFE_FREE(*devmode_ptr);
2166 /****************************************************************************
2167 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2168 ****************************************************************************/
2169 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2171 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2172 NT_PRINTER_PARAM *param_ptr;
2177 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2179 free_nt_devicemode(&info->devmode);
2181 for(param_ptr = info->specific; param_ptr; ) {
2182 NT_PRINTER_PARAM *tofree = param_ptr;
2184 param_ptr = param_ptr->next;
2185 free_nt_printer_param(&tofree);
2188 SAFE_FREE(*info_ptr);
2192 /****************************************************************************
2193 ****************************************************************************/
2194 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2198 NT_DEVICEMODE devmode;
2200 ZERO_STRUCT(devmode);
2202 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2204 if (!*nt_devmode) return len;
2206 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2210 &devmode.specversion,
2211 &devmode.driverversion,
2213 &devmode.driverextra,
2214 &devmode.orientation,
2216 &devmode.paperlength,
2217 &devmode.paperwidth,
2220 &devmode.defaultsource,
2221 &devmode.printquality,
2224 &devmode.yresolution,
2230 &devmode.bitsperpel,
2232 &devmode.pelsheight,
2233 &devmode.displayflags,
2234 &devmode.displayfrequency,
2238 &devmode.dithertype,
2241 &devmode.panningwidth,
2242 &devmode.panningheight,
2245 if (devmode.private) {
2246 /* the len in tdb_unpack is an int value and
2247 * devmode.driverextra is only a short
2249 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2250 devmode.driverextra=(uint16)extra_len;
2252 /* check to catch an invalid TDB entry so we don't segfault */
2253 if (devmode.driverextra == 0) {
2254 devmode.private = NULL;
2258 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2260 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2261 if (devmode.private)
2262 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2267 /****************************************************************************
2268 ****************************************************************************/
2269 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2272 NT_PRINTER_PARAM param, *p;
2277 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2280 len += tdb_unpack(buf+len, buflen-len, "fdB",
2286 *list = memdup(¶m, sizeof(param));
2288 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2294 static void map_to_os2_driver(fstring drivername)
2296 static BOOL initialised=False;
2297 static fstring last_from,last_to;
2298 char *mapfile = lp_os2_driver_map();
2299 char **lines = NULL;
2303 if (!strlen(drivername))
2310 *last_from = *last_to = 0;
2314 if (strequal(drivername,last_from)) {
2315 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2316 fstrcpy(drivername,last_to);
2320 lines = file_lines_load(mapfile, &numlines);
2321 if (numlines == 0) {
2322 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2326 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2328 for( i = 0; i < numlines; i++) {
2329 char *nt_name = lines[i];
2330 char *os2_name = strchr(nt_name,'=');
2337 while (isspace(*nt_name))
2340 if (!*nt_name || strchr("#;",*nt_name))
2344 int l = strlen(nt_name);
2345 while (l && isspace(nt_name[l-1])) {
2351 while (isspace(*os2_name))
2355 int l = strlen(os2_name);
2356 while (l && isspace(os2_name[l-1])) {
2362 if (strequal(nt_name,drivername)) {
2363 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2364 fstrcpy(last_from,drivername);
2365 fstrcpy(last_to,os2_name);
2366 fstrcpy(drivername,os2_name);
2367 file_lines_free(lines);
2372 file_lines_free(lines);
2375 /****************************************************************************
2376 get a default printer info 2 struct
2377 ****************************************************************************/
2378 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2380 extern pstring global_myname;
2382 NT_PRINTER_INFO_LEVEL_2 info;
2386 snum = lp_servicenumber(sharename);
2388 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2389 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2390 global_myname, sharename);
2391 fstrcpy(info.sharename, sharename);
2392 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2393 fstrcpy(info.drivername, lp_printerdriver(snum));
2396 if (!*info.drivername)
2397 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2399 /* by setting the driver name to an empty string, a local NT admin
2400 can now run the **local** APW to install a local printer driver
2401 for a Samba shared printer in 2.2. Without this, drivers **must** be
2402 installed on the Samba server for NT clients --jerry */
2403 if (!*info.drivername)
2404 fstrcpy(info.drivername, "");
2408 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2410 pstrcpy(info.comment, "");
2411 fstrcpy(info.printprocessor, "winprint");
2412 fstrcpy(info.datatype, "RAW");
2414 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2415 | PRINTER_ATTRIBUTE_LOCAL \
2416 | PRINTER_ATTRIBUTE_RAW_ONLY \
2417 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2419 info.starttime = 0; /* Minutes since 12:00am GMT */
2420 info.untiltime = 0; /* Minutes since 12:00am GMT */
2422 info.default_priority = 1;
2423 info.setuptime = (uint32)time(NULL);
2425 #if 1 /* JRA - NO NOT CHANGE ! */
2426 info.devmode = NULL;
2429 * We should not return a default devicemode, as this causes
2430 * Win2K to not send the correct one on PCL drivers. It needs to
2431 * see a null devicemode so it can then overwrite the devicemode
2432 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2434 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2438 /* This will get the current RPC talloc context, but we should be
2439 passing this as a parameter... fixme... JRA ! */
2441 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2444 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2446 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2455 free_nt_devicemode(&info.devmode);
2456 return WERR_ACCESS_DENIED;
2459 /****************************************************************************
2460 ****************************************************************************/
2461 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2464 NT_PRINTER_INFO_LEVEL_2 info;
2466 TDB_DATA kbuf, dbuf;
2467 fstring printername;
2471 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2474 kbuf.dsize = strlen(key)+1;
2476 dbuf = tdb_fetch(tdb_printers, kbuf);
2478 return get_a_printer_2_default(info_ptr, sharename);
2480 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2483 &info.default_priority,
2500 info.printprocessor,
2504 /* Samba has to have shared raw drivers. */
2505 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2507 /* Restore the stripped strings. */
2508 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2509 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2511 fstrcpy(info.printername, printername);
2513 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2514 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2516 /* This will get the current RPC talloc context, but we should be
2517 passing this as a parameter... fixme... JRA ! */
2519 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2521 /* Fix for OS/2 drivers. */
2523 if (get_remote_arch() == RA_OS2)
2524 map_to_os2_driver(info.drivername);
2526 SAFE_FREE(dbuf.dptr);
2527 *info_ptr=memdup(&info, sizeof(info));
2529 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2530 sharename, info.printername, info.drivername));
2535 /****************************************************************************
2536 debugging function, dump at level 6 the struct in the logs
2537 ****************************************************************************/
2538 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2541 NT_PRINTER_INFO_LEVEL_2 *info2;
2543 DEBUG(106,("Dumping printer at level [%d]\n", level));
2549 if (printer.info_2 == NULL)
2553 info2=printer.info_2;
2555 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2556 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2557 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2558 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2559 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2560 DEBUGADD(106,("status:[%s]\n", werror_str(info2->status)));
2561 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2562 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2563 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2564 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2565 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2567 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2568 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2569 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2570 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2571 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2572 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2573 DEBUGADD(106,("location:[%s]\n", info2->location));
2574 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2575 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2576 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2577 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2583 DEBUGADD(1,("Level not implemented\n"));
2591 /****************************************************************************
2592 Get the parameters we can substitute in an NT print job.
2593 ****************************************************************************/
2595 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2597 NT_PRINTER_INFO_LEVEL *printer = NULL;
2599 **printername = **sharename = **portname = '\0';
2601 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2604 fstrcpy(*printername, printer->info_2->printername);
2605 fstrcpy(*sharename, printer->info_2->sharename);
2606 fstrcpy(*portname, printer->info_2->portname);
2608 free_a_printer(&printer, 2);
2612 * The function below are the high level ones.
2613 * only those ones must be called from the spoolss code.
2617 /****************************************************************************
2618 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2619 ****************************************************************************/
2621 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2625 dump_a_printer(printer, level);
2631 printer.info_2->c_setprinter++;
2632 result=update_a_printer_2(printer.info_2);
2636 result=WERR_UNKNOWN_LEVEL;
2643 /****************************************************************************
2644 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2645 We split this out from mod_a_printer as it updates the id's and timestamps.
2646 ****************************************************************************/
2648 WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2652 dump_a_printer(printer, level);
2659 * Update the changestamp.
2660 * Note we must *not* do this in mod_a_printer().
2663 time_t time_unix = time(NULL);
2664 unix_to_nt_time(&time_nt, time_unix);
2665 if (printer.info_2->changeid==time_nt.low)
2666 printer.info_2->changeid++;
2668 printer.info_2->changeid=time_nt.low;
2670 printer.info_2->c_setprinter++;
2672 result=update_a_printer_2(printer.info_2);
2676 result=WERR_UNKNOWN_LEVEL;
2683 /****************************************************************************
2684 Initialize printer devmode & data with previously saved driver init values.
2685 ****************************************************************************/
2686 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2690 TDB_DATA kbuf, dbuf;
2691 NT_PRINTER_PARAM *current;
2692 NT_PRINTER_INFO_LEVEL_2 info;
2696 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2699 kbuf.dsize = strlen(key)+1;
2701 dbuf = tdb_fetch(tdb_drivers, kbuf);
2706 * Get the saved DEVMODE..
2708 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2711 * The saved DEVMODE contains the devicename from the printer used during
2712 * the initialization save. Change it to reflect the new printer.
2714 ZERO_STRUCT(info.devmode->devicename);
2715 fstrcpy(info.devmode->devicename, info_ptr->printername);
2718 * Bind the saved DEVMODE to the new the printer.
2720 free_nt_devicemode(&info_ptr->devmode);
2721 info_ptr->devmode = info.devmode;
2723 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2724 info_ptr->printername, info_ptr->drivername));
2727 * There should not be any printer data 'specifics' already set during the
2728 * add printer operation, if there are delete them.
2730 while ( (current=info_ptr->specific) != NULL ) {
2731 info_ptr->specific=current->next;
2732 SAFE_FREE(current->data);
2737 * Add the printer data 'specifics' to the new printer
2739 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2741 SAFE_FREE(dbuf.dptr);
2746 /****************************************************************************
2747 Initialize printer devmode & data with previously saved driver init values.
2748 When a printer is created using AddPrinter, the drivername bound to the
2749 printer is used to lookup previously saved driver initialization info, which
2750 is bound to the new printer.
2751 ****************************************************************************/
2753 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2761 result=set_driver_init_2(printer->info_2);
2772 /****************************************************************************
2773 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2774 in the tdb. Note: this is different from the driver entry and the printer
2775 entry. There should be a single driver init entry for each driver regardless
2776 of whether it was installed from NT or 2K. Technically, they should be
2777 different, but they work out to the same struct.
2778 ****************************************************************************/
2779 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2783 int buflen, len, ret;
2784 TDB_DATA kbuf, dbuf;
2791 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2793 len += pack_specifics(info->specific, buf+len, buflen-len);
2795 if (buflen != len) {
2798 tb = (char *)Realloc(buf, len);
2800 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2809 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2812 kbuf.dsize = strlen(key)+1;
2816 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2820 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2824 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2825 info->sharename, info->drivername));
2830 /****************************************************************************
2831 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2832 ****************************************************************************/
2834 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2838 dump_a_printer(printer, level);
2844 result=update_driver_init_2(printer.info_2);
2855 /****************************************************************************
2856 Convert the printer data value, a REG_BINARY array, into an initialization
2857 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2858 got to keep the endians happy :).
2859 ****************************************************************************/
2861 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2863 BOOL result = False;
2867 ZERO_STRUCT(devmode);
2869 prs_init(&ps, 0, ctx, UNMARSHALL);
2870 ps.data_p = (char *)param->data;
2871 ps.buffer_size = param->data_len;
2873 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2874 result = convert_devicemode("", &devmode, &nt_devmode);
2876 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2881 /****************************************************************************
2882 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2884 1. Use the driver's config DLL to this UNC printername and:
2885 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2886 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2887 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2889 The last step triggers saving the "driver initialization" information for
2890 this printer into the tdb. Later, new printers that use this driver will
2891 have this initialization information bound to them. This simulates the
2892 driver initialization, as if it had run on the Samba server (as it would
2895 The Win32 client side code requirement sucks! But until we can run arbitrary
2896 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2898 It would have been easier to use SetPrinter because all the UNMARSHALLING of
2899 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2900 about it and you will realize why. JRR 010720
2901 ****************************************************************************/
2903 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2905 WERROR status = WERR_OK;
2906 TALLOC_CTX *ctx = NULL;
2907 NT_DEVICEMODE *nt_devmode = NULL;
2908 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2911 * Set devmode on printer info, so entire printer initialization can be
2914 if ((ctx = talloc_init()) == NULL)
2917 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2918 status = WERR_NOMEM;
2922 ZERO_STRUCTP(nt_devmode);
2925 * The DEVMODE is held in the 'data' component of the param in raw binary.
2926 * Convert it to to a devmode structure
2928 if (!convert_driver_init(param, ctx, nt_devmode)) {
2929 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
2930 status = WERR_INVALID_PARAM;
2935 * Pack up and add (or update) the DEVMODE and any current printer data to
2936 * a 'driver init' element in the tdb
2939 printer->info_2->devmode = nt_devmode;
2940 if (update_driver_init(*printer, 2)!=0) {
2941 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
2942 status = WERR_NOMEM;
2947 * If driver initialization info was successfully saved, set the current
2948 * printer to match it. This allows initialization of the current printer
2949 * as well as the driver.
2951 status = mod_a_printer(*printer, 2);
2952 if (!W_ERROR_IS_OK(status)) {
2953 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
2954 printer->info_2->printername));
2958 talloc_destroy(ctx);
2960 SAFE_FREE(nt_devmode->private);
2961 SAFE_FREE(nt_devmode);
2962 printer->info_2->devmode = tmp_devmode;
2967 /****************************************************************************
2968 Update the driver init info (DEVMODE and specifics) for a printer
2969 ****************************************************************************/
2971 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
2973 WERROR status = WERR_OK;
2979 status=save_driver_init_2(printer, param);
2983 status=WERR_UNKNOWN_LEVEL;
2990 /****************************************************************************
2991 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2992 ****************************************************************************/
2994 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2997 NT_PRINTER_INFO_LEVEL *printer = NULL;
3001 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3007 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3008 DEBUG(0,("get_a_printer: malloc fail.\n"));
3011 ZERO_STRUCTP(printer);
3012 result=get_a_printer_2(&printer->info_2, sharename);
3013 if (W_ERROR_IS_OK(result)) {
3014 dump_a_printer(*printer, level);
3015 *pp_printer = printer;
3022 result=WERR_UNKNOWN_LEVEL;
3026 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, werror_str(result)));
3031 /****************************************************************************
3032 Deletes a NT_PRINTER_INFO_LEVEL struct.
3033 ****************************************************************************/
3035 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3038 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3040 DEBUG(104,("freeing a printer at level [%d]\n", level));
3042 if (printer == NULL)
3049 if (printer->info_2 != NULL)
3051 free_nt_printer_info_level_2(&printer->info_2);
3065 SAFE_FREE(*pp_printer);
3069 /****************************************************************************
3070 ****************************************************************************/
3071 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3074 DEBUG(104,("adding a printer at level [%d]\n", level));
3075 dump_a_printer_driver(driver, level);
3081 result=add_a_printer_driver_3(driver.info_3);
3087 result=add_a_printer_driver_6(driver.info_6);
3097 /****************************************************************************
3098 ****************************************************************************/
3099 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3100 fstring printername, fstring architecture, uint32 version)
3108 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3116 if (W_ERROR_IS_OK(result))
3117 dump_a_printer_driver(*driver, level);
3121 /****************************************************************************
3122 ****************************************************************************/
3123 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3131 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3132 if (driver.info_3 != NULL)
3134 info3=driver.info_3;
3135 SAFE_FREE(info3->dependentfiles);
3136 ZERO_STRUCTP(info3);
3148 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3149 if (driver.info_6 != NULL)
3151 info6=driver.info_6;
3152 SAFE_FREE(info6->dependentfiles);
3153 SAFE_FREE(info6->previousnames);
3154 ZERO_STRUCTP(info6);
3172 /****************************************************************************
3173 Determine whether or not a particular driver is currently assigned
3175 ****************************************************************************/
3176 BOOL printer_driver_in_use (char *arch, char *driver)
3178 TDB_DATA kbuf, newkey, dbuf;
3179 NT_PRINTER_INFO_LEVEL_2 info;
3183 if (!nt_printing_init())
3186 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3188 /* loop through the printers.tdb and check for the drivername */
3189 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3190 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3193 dbuf = tdb_fetch(tdb_printers, kbuf);
3197 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3200 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3203 &info.default_priority,
3220 info.printprocessor,
3224 SAFE_FREE(dbuf.dptr);
3227 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3232 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3233 info.printername, info.drivername));
3235 if (strcmp(info.drivername, driver) == 0)
3237 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3238 info.printername, driver));
3242 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3246 /* report that the driver is in use by default */
3250 /****************************************************************************
3251 Remove a printer driver from the TDB. This assumes that the the driver was
3252 previously looked up.
3253 ***************************************************************************/
3254 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3261 get_short_archi(arch, i->environment);
3262 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3263 arch, i->cversion, i->name);
3264 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3267 kbuf.dsize=strlen(key)+1;
3269 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3270 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3271 return WERR_ACCESS_DENIED;
3274 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3279 /****************************************************************************
3280 ****************************************************************************/
3281 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3282 fstring value, uint8 **data, uint32 *type, uint32 *len)
3284 /* right now that's enough ! */
3285 NT_PRINTER_PARAM *param;
3288 param=printer.info_2->specific;
3290 while (param != NULL && i < param_index) {
3298 /* exited because it exist */
3300 StrnCpy(value, param->value, sizeof(fstring)-1);
3301 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3304 ZERO_STRUCTP(*data);
3305 memcpy(*data, param->data, param->data_len);
3306 *len=param->data_len;
3310 /****************************************************************************
3311 ****************************************************************************/
3312 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3313 fstring value, uint8 **data, uint32 *type, uint32 *len)
3315 /* right now that's enough ! */
3316 NT_PRINTER_PARAM *param;
3318 DEBUG(10, ("get_specific_param\n"));
3320 param=printer.info_2->specific;
3322 while (param != NULL)
3324 #if 1 /* JRA - I think this should be case insensitive.... */
3325 if ( strequal(value, param->value)
3327 if ( !strcmp(value, param->value)
3329 && strlen(value)==strlen(param->value))
3337 DEBUGADD(10, ("get_specific_param: found one param\n"));
3338 /* exited because it exist */
3341 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3344 memcpy(*data, param->data, param->data_len);
3345 *len=param->data_len;
3347 DEBUGADD(10, ("get_specific_param: exit true\n"));
3350 DEBUGADD(10, ("get_specific_param: exit false\n"));
3354 /****************************************************************************
3355 Store a security desc for a printer.
3356 ****************************************************************************/
3358 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3360 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3361 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3363 TALLOC_CTX *mem_ctx = NULL;
3367 mem_ctx = talloc_init();
3368 if (mem_ctx == NULL)
3371 /* The old owner and group sids of the security descriptor are not
3372 present when new ACEs are added or removed by changing printer
3373 permissions through NT. If they are NULL in the new security
3374 descriptor then copy them over from the old one. */
3376 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3377 DOM_SID *owner_sid, *group_sid;
3378 SEC_ACL *dacl, *sacl;
3379 SEC_DESC *psd = NULL;
3382 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3384 /* Pick out correct owner and group sids */
3386 owner_sid = secdesc_ctr->sec->owner_sid ?
3387 secdesc_ctr->sec->owner_sid :
3388 old_secdesc_ctr->sec->owner_sid;
3390 group_sid = secdesc_ctr->sec->grp_sid ?
3391 secdesc_ctr->sec->grp_sid :
3392 old_secdesc_ctr->sec->grp_sid;
3394 dacl = secdesc_ctr->sec->dacl ?
3395 secdesc_ctr->sec->dacl :
3396 old_secdesc_ctr->sec->dacl;
3398 sacl = secdesc_ctr->sec->sacl ?
3399 secdesc_ctr->sec->sacl :
3400 old_secdesc_ctr->sec->sacl;
3402 /* Make a deep copy of the security descriptor */
3404 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3405 owner_sid, group_sid,
3410 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3413 if (!new_secdesc_ctr) {
3414 new_secdesc_ctr = secdesc_ctr;
3417 /* Store the security descriptor in a tdb */
3419 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3420 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3422 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3424 status = WERR_BADFUNC;
3428 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3430 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3433 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3434 status = WERR_BADFUNC;
3437 /* Free malloc'ed memory */
3443 talloc_destroy(mem_ctx);
3447 /****************************************************************************
3448 Construct a default security descriptor buffer for a printer.
3449 ****************************************************************************/
3451 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3455 SEC_ACL *psa = NULL;
3456 SEC_DESC_BUF *sdb = NULL;
3457 SEC_DESC *psd = NULL;
3460 enum SID_NAME_USE name_type;
3462 /* Create an ACE where Everyone is allowed to print */
3464 init_sec_access(&sa, PRINTER_ACE_PRINT);
3465 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3466 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3468 /* Make the security descriptor owned by the Administrators group
3469 on the PDC of the domain. */
3471 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3472 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3476 /* Backup plan - make printer owned by admins or root.
3477 This should emulate a lanman printer as security
3478 settings can't be changed. */
3480 sid_peek_rid(&owner_sid, &owner_rid);
3482 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3483 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3484 owner_rid != DOMAIN_USER_RID_ADMIN &&
3485 !lookup_name("root", &owner_sid, &name_type)) {
3486 sid_copy(&owner_sid, &global_sid_World);
3490 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3491 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3492 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3493 SEC_ACE_FLAG_INHERIT_ONLY);
3495 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3496 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3497 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3499 /* The ACL revision number in rpc_secdesc.h differs from the one
3500 created by NT when setting ACE entries in printer
3501 descriptors. NT4 complains about the property being edited by a
3504 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3505 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3507 NULL, psa, &sd_size);
3511 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3515 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3517 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3518 (unsigned int)sd_size));
3523 /****************************************************************************
3524 Get a security desc for a printer.
3525 ****************************************************************************/
3527 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3533 if ((temp = strchr(printername + 2, '\\'))) {
3534 printername = temp + 1;
3537 /* Fetch security descriptor from tdb */
3539 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3541 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3542 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3544 DEBUG(4,("using default secdesc for %s\n", printername));
3546 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3553 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3554 this security descriptor has been created when winbindd was
3555 down. Take ownership of security descriptor. */
3557 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3559 enum SID_NAME_USE name_type;
3561 /* Change sd owner to workgroup administrator */
3563 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3565 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3566 SEC_DESC *psd = NULL;
3571 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3573 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3575 (*secdesc_ctr)->sec->grp_sid,
3576 (*secdesc_ctr)->sec->sacl,
3577 (*secdesc_ctr)->sec->dacl,
3580 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3582 /* Swap with other one */
3584 *secdesc_ctr = new_secdesc_ctr;
3588 nt_printing_setsec(printername, *secdesc_ctr);
3592 if (DEBUGLEVEL >= 10) {
3593 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3596 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3597 printername, the_acl->num_aces));
3599 for (i = 0; i < the_acl->num_aces; i++) {
3602 sid_to_string(sid_str, &the_acl->ace[i].sid);
3604 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3605 the_acl->ace[i].type, the_acl->ace[i].flags,
3606 the_acl->ace[i].info.mask));
3616 1: level not implemented
3617 2: file doesn't exist
3618 3: can't allocate memory
3619 4: can't free memory
3620 5: non existant struct
3624 A printer and a printer driver are 2 different things.
3625 NT manages them separatelly, Samba does the same.
3626 Why ? Simply because it's easier and it makes sense !
3628 Now explanation: You have 3 printers behind your samba server,
3629 2 of them are the same make and model (laser A and B). But laser B
3630 has an 3000 sheet feeder and laser A doesn't such an option.
3631 Your third printer is an old dot-matrix model for the accounting :-).
3633 If the /usr/local/samba/lib directory (default dir), you will have
3634 5 files to describe all of this.
3636 3 files for the printers (1 by printer):
3639 NTprinter_accounting
3640 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3641 NTdriver_printer model X
3642 NTdriver_printer model Y
3644 jfm: I should use this comment for the text file to explain
3645 same thing for the forms BTW.
3646 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3650 /* Convert generic access rights to printer object specific access rights.
3651 It turns out that NT4 security descriptors use generic access rights and
3652 NT5 the object specific ones. */
3654 void map_printer_permissions(SEC_DESC *sd)
3658 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3659 se_map_generic(&sd->dacl->ace[i].info.mask,
3660 &printer_generic_mapping);
3664 /****************************************************************************
3665 Check a user has permissions to perform the given operation. We use the
3666 permission constants defined in include/rpc_spoolss.h to check the various
3667 actions we perform when checking printer access.
3669 PRINTER_ACCESS_ADMINISTER:
3670 print_queue_pause, print_queue_resume, update_printer_sec,
3671 update_printer, spoolss_addprinterex_level_2,
3672 _spoolss_setprinterdata
3677 JOB_ACCESS_ADMINISTER:
3678 print_job_delete, print_job_pause, print_job_resume,
3681 ****************************************************************************/
3682 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3684 SEC_DESC_BUF *secdesc = NULL;
3685 uint32 access_granted;
3689 TALLOC_CTX *mem_ctx = NULL;
3690 extern struct current_user current_user;
3692 /* If user is NULL then use the current_user structure */
3695 user = ¤t_user;
3697 /* Always allow root or printer admins to do anything */
3699 if (user->uid == 0 ||
3700 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3704 /* Get printer name */
3706 pname = PRINTERNAME(snum);
3708 if (!pname || !*pname) {
3713 /* Get printer security descriptor */
3715 if(!(mem_ctx = talloc_init())) {
3720 nt_printing_getsec(mem_ctx, pname, &secdesc);
3722 if (access_type == JOB_ACCESS_ADMINISTER) {
3723 SEC_DESC_BUF *parent_secdesc = secdesc;
3725 /* Create a child security descriptor to check permissions
3726 against. This is because print jobs are child objects
3727 objects of a printer. */
3729 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3731 /* Now this is the bit that really confuses me. The access
3732 type needs to be changed from JOB_ACCESS_ADMINISTER to
3733 PRINTER_ACCESS_ADMINISTER for this to work. Something
3734 to do with the child (job) object becoming like a
3737 access_type = PRINTER_ACCESS_ADMINISTER;
3742 map_printer_permissions(secdesc->sec);
3744 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
3745 &access_granted, &status);
3747 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3749 talloc_destroy(mem_ctx);
3757 /****************************************************************************
3758 Check the time parameters allow a print operation.
3759 *****************************************************************************/
3761 BOOL print_time_access_check(int snum)
3763 NT_PRINTER_INFO_LEVEL *printer = NULL;
3765 time_t now = time(NULL);
3769 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3772 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3776 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3778 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3781 free_a_printer(&printer, 2);
3789 /****************************************************************************
3790 Attempt to write a default device.
3791 *****************************************************************************/
3793 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3795 NT_PRINTER_INFO_LEVEL *printer = NULL;
3799 * Don't bother if no default devicemode was sent.
3802 if (printer_default->devmode_cont.devmode == NULL)
3805 result = get_a_printer(&printer, 2, lp_servicename(snum));
3806 if (!W_ERROR_IS_OK(result)) return result;
3809 * Just ignore it if we already have a devmode.
3812 if (printer->info_2->devmode != NULL)
3816 * We don't have a devicemode and we're trying to write
3817 * one. Check we have the access needed.
3819 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3821 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3822 PRINTER_ACCESS_ADMINISTER) {
3823 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3824 result = WERR_ACCESS_DENIED;
3828 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3829 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3830 lp_servicename(snum) ));
3831 result = WERR_ACCESS_DENIED;
3832 /*result = NT_STATUS_NO_PROBLEMO;*/
3836 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3839 * Convert the on the wire devicemode format to the internal one.
3842 if (!convert_devicemode(printer->info_2->printername,
3843 printer_default->devmode_cont.devmode,
3844 &printer->info_2->devmode)) {
3845 result = WERR_NOMEM;
3850 * Finally write back to the tdb.
3853 result = add_a_printer(*printer, 2);
3857 free_a_printer(&printer, 2);