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 pstring global_myname;
26 extern DOM_SID global_sid_World;
28 static TDB_CONTEXT *tdb_forms; /* used for forms files */
29 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
30 static TDB_CONTEXT *tdb_printers; /* used for printers files */
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
35 #define PRINTERS_PREFIX "PRINTERS/"
36 #define SECDESC_PREFIX "SECDESC/"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
41 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_2
43 /* Map generic permissions to printer object specific permissions */
45 struct generic_mapping printer_generic_mapping = {
52 /* We need one default form to support our default printer. Msoft adds the
53 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
54 array index). Letter is always first, so (for the current code) additions
55 always put things in the correct order. */
56 static nt_forms_struct default_forms[] = {
57 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
58 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
59 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
60 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
61 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
62 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
63 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
64 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
65 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
66 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
67 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
68 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
69 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
70 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
71 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
72 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
73 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
74 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
75 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
76 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
77 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
78 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
79 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
80 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
81 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
82 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
83 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
84 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
85 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
86 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
87 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
88 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
89 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
90 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
91 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
92 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
93 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
94 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
95 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
96 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
97 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
98 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
99 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
100 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
101 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
102 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
103 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
104 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
105 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
106 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
107 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
108 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
109 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
110 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
111 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
112 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
113 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
114 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
115 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
116 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
117 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
118 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
119 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
120 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
121 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
122 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
123 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
124 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
125 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
126 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
127 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
128 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
129 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
130 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
131 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
132 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
133 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
134 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
135 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
136 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
137 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
138 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
139 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
140 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
141 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
142 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
143 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
144 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
145 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
146 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
147 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
148 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
149 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
150 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
151 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
152 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
153 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
154 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
155 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
156 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
157 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
158 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
159 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
160 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
161 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
162 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
163 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
164 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
165 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
166 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
167 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
168 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
169 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
170 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
171 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
172 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
173 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
174 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
177 static BOOL upgrade_to_version_2(void)
179 TDB_DATA kbuf, newkey, dbuf;
181 DEBUG(0,("upgrade_to_version_2: upgrading print tdb's to version 2\n"));
183 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
184 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
186 dbuf = tdb_fetch(tdb_drivers, kbuf);
188 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
189 DEBUG(0,("upgrade_to_version_2:moving form\n"));
190 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
191 DEBUG(0,("upgrade_to_version_2: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
194 if (tdb_delete(tdb_drivers, kbuf) != 0) {
195 DEBUG(0,("upgrade_to_version_2: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
200 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
201 DEBUG(0,("upgrade_to_version_2:moving printer\n"));
202 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
203 DEBUG(0,("upgrade_to_version_2: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
206 if (tdb_delete(tdb_drivers, kbuf) != 0) {
207 DEBUG(0,("upgrade_to_version_2: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
212 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
213 DEBUG(0,("upgrade_to_version_2:moving secdesc\n"));
214 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
215 DEBUG(0,("upgrade_to_version_2: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
218 if (tdb_delete(tdb_drivers, kbuf) != 0) {
219 DEBUG(0,("upgrade_to_version_2: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
224 SAFE_FREE(dbuf.dptr);
230 /****************************************************************************
231 open the NT printing tdb
232 ****************************************************************************/
233 BOOL nt_printing_init(void)
235 static pid_t local_pid;
236 char *vstring = "INFO/version";
238 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
241 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
243 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
244 lock_path("ntdrivers.tdb"), strerror(errno) ));
248 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
250 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
251 lock_path("ntprinters.tdb"), strerror(errno) ));
255 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
257 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
258 lock_path("ntforms.tdb"), strerror(errno) ));
262 local_pid = sys_getpid();
264 /* handle a Samba upgrade */
265 tdb_lock_bystring(tdb_drivers, vstring);
266 if (tdb_fetch_int(tdb_drivers, vstring) != NTDRIVERS_DATABASE_VERSION) {
268 if (tdb_fetch_int(tdb_drivers, vstring) == NTDRIVERS_DATABASE_VERSION_1) {
269 if (!upgrade_to_version_2())
272 tdb_traverse(tdb_drivers, (tdb_traverse_func)tdb_delete, NULL);
274 tdb_store_int(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
276 tdb_unlock_bystring(tdb_drivers, vstring);
281 /****************************************************************************
282 get builtin form struct list
283 ****************************************************************************/
284 int get_builtin_ntforms(nt_forms_struct **list)
286 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
287 return sizeof(default_forms) / sizeof(default_forms[0]);
290 /****************************************************************************
291 get a builtin form struct
292 ****************************************************************************/
294 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
298 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
299 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
300 count = sizeof(default_forms) / sizeof(default_forms[0]);
301 for (i=0;i<count;i++) {
302 if (strequal(form_name,default_forms[i].name)) {
303 DEBUGADD(6,("Found builtin form %s \n", form_name));
304 memcpy(form,&default_forms[i],sizeof(*form));
312 /****************************************************************************
313 get a form struct list
314 ****************************************************************************/
315 int get_ntforms(nt_forms_struct **list)
317 TDB_DATA kbuf, newkey, dbuf;
319 nt_forms_struct form;
324 for (kbuf = tdb_firstkey(tdb_forms);
326 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
327 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
329 dbuf = tdb_fetch(tdb_forms, kbuf);
330 if (!dbuf.dptr) continue;
332 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
333 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
334 &i, &form.flag, &form.width, &form.length, &form.left,
335 &form.top, &form.right, &form.bottom);
336 SAFE_FREE(dbuf.dptr);
337 if (ret != dbuf.dsize) continue;
339 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
341 DEBUG(0,("get_ntforms: Realloc fail.\n"));
353 /****************************************************************************
354 write a form struct list
355 ****************************************************************************/
356 int write_ntforms(nt_forms_struct **list, int number)
363 for (i=0;i<number;i++) {
364 /* save index, so list is rebuilt in correct order */
365 len = tdb_pack(buf, sizeof(buf), "dddddddd",
366 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
367 (*list)[i].left, (*list)[i].top, (*list)[i].right,
369 if (len > sizeof(buf)) break;
370 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
371 kbuf.dsize = strlen(key)+1;
375 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
381 /****************************************************************************
382 add a form struct at the end of the list
383 ****************************************************************************/
384 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
392 * NT tries to add forms even when
393 * they are already in the base
394 * only update the values if already present
399 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
400 for (n=0; n<*count; n++) {
401 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
402 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
409 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
410 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
414 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
418 (*list)[n].flag=form->flags;
419 (*list)[n].width=form->size_x;
420 (*list)[n].length=form->size_y;
421 (*list)[n].left=form->left;
422 (*list)[n].top=form->top;
423 (*list)[n].right=form->right;
424 (*list)[n].bottom=form->bottom;
429 /****************************************************************************
430 delete a named form struct
431 ****************************************************************************/
432 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
441 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
443 for (n=0; n<*count; n++) {
444 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
445 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
451 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
452 *ret = WERR_INVALID_PARAM;
456 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
457 kbuf.dsize = strlen(key)+1;
459 if (tdb_delete(tdb_forms, kbuf) != 0) {
467 /****************************************************************************
469 ****************************************************************************/
470 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
474 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
476 DEBUG(106, ("[%s]\n", form_name));
477 for (n=0; n<count; n++)
479 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
480 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
484 if (n==count) return;
486 (*list)[n].flag=form->flags;
487 (*list)[n].width=form->size_x;
488 (*list)[n].length=form->size_y;
489 (*list)[n].left=form->left;
490 (*list)[n].top=form->top;
491 (*list)[n].right=form->right;
492 (*list)[n].bottom=form->bottom;
495 /****************************************************************************
496 get the nt drivers list
498 traverse the database and look-up the matching names
499 ****************************************************************************/
500 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
506 TDB_DATA kbuf, newkey;
508 get_short_archi(short_archi, architecture);
509 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
511 for (kbuf = tdb_firstkey(tdb_drivers);
513 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
514 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
516 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
517 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
522 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
529 /****************************************************************************
530 function to do the mapping between the long architecture name and
532 ****************************************************************************/
533 BOOL get_short_archi(char *short_archi, char *long_archi)
540 struct table archi_table[]=
542 {"Windows 4.0", "WIN40" },
543 {"Windows NT x86", "W32X86" },
544 {"Windows NT R4000", "W32MIPS" },
545 {"Windows NT Alpha_AXP", "W32ALPHA" },
546 {"Windows NT PowerPC", "W32PPC" },
552 DEBUG(107,("Getting architecture dependant directory\n"));
555 } while ( (archi_table[i].long_archi!=NULL ) &&
556 StrCaseCmp(long_archi, archi_table[i].long_archi) );
558 if (archi_table[i].long_archi==NULL) {
559 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
563 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
565 DEBUGADD(108,("index: [%d]\n", i));
566 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
567 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
572 /****************************************************************************
573 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
574 There are two case to be covered here: PE (Portable Executable) and NE (New
575 Executable) files. Both files support the same INFO structure, but PE files
576 store the signature in unicode, and NE files store it as !unicode.
577 ****************************************************************************/
578 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
585 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
586 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
587 fname, PE_HEADER_SIZE));
591 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
592 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
593 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
595 goto no_version_info;
598 /* Is this really a DOS header? */
599 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
600 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
601 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
602 goto no_version_info;
605 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
606 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
607 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
609 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
610 goto no_version_info;
613 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
614 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
616 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
617 goto no_version_info;
620 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
621 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
623 int section_table_bytes;
625 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
626 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
627 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
628 /* At this point, we assume the file is in error. It still could be somthing
629 * else besides a PE file, but it unlikely at this point.
634 /* get the section table */
635 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
636 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
638 if ((buf=malloc(section_table_bytes)) == NULL) {
639 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
640 fname, section_table_bytes));
644 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
645 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
650 /* Iterate the section table looking for the resource section ".rsrc" */
651 for (i = 0; i < num_sections; i++) {
652 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
654 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
655 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
656 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
659 if ((buf=malloc(section_bytes)) == NULL) {
660 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
661 fname, section_bytes));
665 /* Seek to the start of the .rsrc section info */
666 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
667 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
672 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
673 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
678 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
679 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
680 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
681 /* Align to next long address */
682 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
684 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
685 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
686 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
688 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
689 fname, *major, *minor,
690 (*major>>16)&0xffff, *major&0xffff,
691 (*minor>>16)&0xffff, *minor&0xffff));
700 /* Version info not found, fall back to origin date/time */
701 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
705 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
706 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
707 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
708 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
709 /* At this point, we assume the file is in error. It still could be somthing
710 * else besides a NE file, but it unlikely at this point. */
714 /* Allocate a bit more space to speed up things */
716 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
717 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
718 fname, PE_HEADER_SIZE));
722 /* This is a HACK! I got tired of trying to sort through the messy
723 * 'NE' file format. If anyone wants to clean this up please have at
724 * it, but this works. 'NE' files will eventually fade away. JRR */
725 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
726 /* Cover case that should not occur in a well formed 'NE' .dll file */
727 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
729 for(i=0; i<byte_count; i++) {
730 /* Fast skip past data that can't possibly match */
731 if (buf[i] != 'V') continue;
733 /* Potential match data crosses buf boundry, move it to beginning
734 * of buf, and fill the buf with as much as it will hold. */
735 if (i>byte_count-VS_VERSION_INFO_SIZE) {
738 memcpy(buf, &buf[i], byte_count-i);
739 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
740 (byte_count-i))) < 0) {
742 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
747 byte_count = bc + (byte_count - i);
748 if (byte_count<VS_VERSION_INFO_SIZE) break;
753 /* Check that the full signature string and the magic number that
754 * follows exist (not a perfect solution, but the chances that this
755 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
756 * twice, as it is simpler to read the code. */
757 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
758 /* Compute skip alignment to next long address */
759 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
760 sizeof(VS_SIGNATURE)) & 3;
761 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
763 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
764 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
765 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
766 fname, *major, *minor,
767 (*major>>16)&0xffff, *major&0xffff,
768 (*minor>>16)&0xffff, *minor&0xffff));
775 /* Version info not found, fall back to origin date/time */
776 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
781 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
782 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
783 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
794 /****************************************************************************
795 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
796 share one or more files. During the MS installation process files are checked
797 to insure that only a newer version of a shared file is installed over an
798 older version. There are several possibilities for this comparison. If there
799 is no previous version, the new one is newer (obviously). If either file is
800 missing the version info structure, compare the creation date (on Unix use
801 the modification date). Otherwise chose the numerically larger version number.
802 ****************************************************************************/
803 static int file_version_is_newer(connection_struct *conn, fstring new_file,
806 BOOL use_version = True;
811 time_t new_create_time;
815 time_t old_create_time;
819 files_struct *fsp = NULL;
821 SMB_STRUCT_STAT stat_buf;
825 ZERO_STRUCT(stat_buf);
826 new_create_time = (time_t)0;
827 old_create_time = (time_t)0;
829 /* Get file version info (if available) for previous file (if it exists) */
830 pstrcpy(filepath, old_file);
832 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
834 fsp = open_file_shared(conn, filepath, &stat_buf,
835 SET_OPEN_MODE(DOS_OPEN_RDONLY),
836 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
837 0, 0, &access_mode, &action);
839 /* Old file not found, so by definition new file is in fact newer */
840 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
845 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
846 if (ret == -1) goto error_exit;
849 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
852 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
853 old_create_time = st.st_mtime;
854 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
857 close_file(fsp, True);
859 /* Get file version info (if available) for new file */
860 pstrcpy(filepath, new_file);
861 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
863 fsp = open_file_shared(conn, filepath, &stat_buf,
864 SET_OPEN_MODE(DOS_OPEN_RDONLY),
865 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
866 0, 0, &access_mode, &action);
868 /* New file not found, this shouldn't occur if the caller did its job */
869 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
874 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
875 if (ret == -1) goto error_exit;
878 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
881 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
882 new_create_time = st.st_mtime;
883 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
886 close_file(fsp, True);
889 /* Compare versions and choose the larger version number */
890 if (new_major > old_major ||
891 (new_major == old_major && new_minor > old_minor)) {
893 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
897 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
902 /* Compare modification time/dates and choose the newest time/date */
903 if (new_create_time > old_create_time) {
904 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
908 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
915 close_file(fsp, True);
919 /****************************************************************************
920 Determine the correct cVersion associated with an architecture and driver
921 ****************************************************************************/
922 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
923 struct current_user *user, WERROR *perr)
931 files_struct *fsp = NULL;
934 connection_struct *conn;
938 /* If architecture is Windows 95/98/ME, the version is always 0. */
939 if (strcmp(architecture, "WIN40") == 0) {
940 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
944 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
945 /* Null password is ok - we are already an authenticated user... */
947 conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status);
950 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
951 *perr = ntstatus_to_werror(nt_status);
955 /* Save who we are - we are temporarily becoming the connection user. */
958 if (!become_user(conn, conn->vuid)) {
959 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
960 *perr = WERR_ACCESS_DENIED;
965 /* Open the driver file (Portable Executable format) and determine the
966 * deriver the cversion. */
967 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
969 unix_convert(driverpath,conn,NULL,&bad_path,&st);
971 fsp = open_file_shared(conn, driverpath, &st,
972 SET_OPEN_MODE(DOS_OPEN_RDONLY),
973 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
974 0, 0, &access_mode, &action);
976 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
978 *perr = WERR_ACCESS_DENIED;
984 int ret = get_file_version(fsp, driverpath, &major, &minor);
985 if (ret == -1) goto error_exit;
988 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
993 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
994 * for more details. Version in this case is not just the version of the
995 * file, but the version in the sense of kernal mode (2) vs. user mode
996 * (3) drivers. Other bits of the version fields are the version info.
999 cversion = major & 0x0000ffff;
1001 case 2: /* WinNT drivers */
1002 case 3: /* Win2K drivers */
1006 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1007 driverpath, cversion));
1011 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1012 driverpath, major, minor));
1015 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1016 driverpath, cversion));
1018 close_file(fsp, True);
1019 close_cnum(conn, user->vuid);
1026 close_file(fsp, True);
1028 close_cnum(conn, user->vuid);
1033 /****************************************************************************
1034 ****************************************************************************/
1035 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1036 struct current_user *user)
1038 fstring architecture;
1044 /* clean up the driver name.
1045 * we can get .\driver.dll
1046 * or worse c:\windows\system\driver.dll !
1048 /* using an intermediate string to not have overlaping memcpy()'s */
1049 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1050 fstrcpy(new_name, p+1);
1051 fstrcpy(driver->driverpath, new_name);
1054 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1055 fstrcpy(new_name, p+1);
1056 fstrcpy(driver->datafile, new_name);
1059 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1060 fstrcpy(new_name, p+1);
1061 fstrcpy(driver->configfile, new_name);
1064 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1065 fstrcpy(new_name, p+1);
1066 fstrcpy(driver->helpfile, new_name);
1069 if (driver->dependentfiles) {
1070 for (i=0; *driver->dependentfiles[i]; i++) {
1071 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1072 fstrcpy(new_name, p+1);
1073 fstrcpy(driver->dependentfiles[i], new_name);
1078 get_short_archi(architecture, driver->environment);
1080 /* jfm:7/16/2000 the client always sends the cversion=0.
1081 * The server should check which version the driver is by reading
1082 * the PE header of driver->driverpath.
1084 * For Windows 95/98 the version is 0 (so the value sent is correct)
1085 * For Windows NT (the architecture doesn't matter)
1086 * NT 3.1: cversion=0
1087 * NT 3.5/3.51: cversion=1
1091 if ((driver->cversion = get_correct_cversion( architecture,
1092 driver->driverpath, user, &err)) == -1)
1098 /****************************************************************************
1099 ****************************************************************************/
1100 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1101 struct current_user *user)
1103 fstring architecture;
1109 /* clean up the driver name.
1110 * we can get .\driver.dll
1111 * or worse c:\windows\system\driver.dll !
1113 /* using an intermediate string to not have overlaping memcpy()'s */
1114 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1115 fstrcpy(new_name, p+1);
1116 fstrcpy(driver->driverpath, new_name);
1119 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1120 fstrcpy(new_name, p+1);
1121 fstrcpy(driver->datafile, new_name);
1124 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1125 fstrcpy(new_name, p+1);
1126 fstrcpy(driver->configfile, new_name);
1129 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1130 fstrcpy(new_name, p+1);
1131 fstrcpy(driver->helpfile, new_name);
1134 if (driver->dependentfiles) {
1135 for (i=0; *driver->dependentfiles[i]; i++) {
1136 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1137 fstrcpy(new_name, p+1);
1138 fstrcpy(driver->dependentfiles[i], new_name);
1143 get_short_archi(architecture, driver->environment);
1145 /* jfm:7/16/2000 the client always sends the cversion=0.
1146 * The server should check which version the driver is by reading
1147 * the PE header of driver->driverpath.
1149 * For Windows 95/98 the version is 0 (so the value sent is correct)
1150 * For Windows NT (the architecture doesn't matter)
1151 * NT 3.1: cversion=0
1152 * NT 3.5/3.51: cversion=1
1156 if ((driver->version = get_correct_cversion(architecture,
1157 driver->driverpath, user, &err)) == -1)
1163 /****************************************************************************
1164 ****************************************************************************/
1165 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1166 uint32 level, struct current_user *user)
1171 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1172 driver=driver_abstract.info_3;
1173 return clean_up_driver_struct_level_3(driver, user);
1177 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1178 driver=driver_abstract.info_6;
1179 return clean_up_driver_struct_level_6(driver, user);
1182 return WERR_INVALID_PARAM;
1186 /****************************************************************************
1187 This function sucks and should be replaced. JRA.
1188 ****************************************************************************/
1190 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1192 dst->cversion = src->version;
1194 fstrcpy( dst->name, src->name);
1195 fstrcpy( dst->environment, src->environment);
1196 fstrcpy( dst->driverpath, src->driverpath);
1197 fstrcpy( dst->datafile, src->datafile);
1198 fstrcpy( dst->configfile, src->configfile);
1199 fstrcpy( dst->helpfile, src->helpfile);
1200 fstrcpy( dst->monitorname, src->monitorname);
1201 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1202 dst->dependentfiles = src->dependentfiles;
1205 #if 0 /* Debugging function */
1207 static char* ffmt(unsigned char *c){
1209 static char ffmt_str[17];
1211 for (i=0; i<16; i++) {
1212 if ((c[i] < ' ') || (c[i] > '~'))
1223 /****************************************************************************
1224 ****************************************************************************/
1225 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1226 struct current_user *user, WERROR *perr)
1228 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1229 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1230 fstring architecture;
1235 connection_struct *conn;
1243 driver=driver_abstract.info_3;
1244 else if (level==6) {
1245 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1246 driver = &converted_driver;
1248 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1252 get_short_archi(architecture, driver->environment);
1254 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1255 /* Null password is ok - we are already an authenticated user... */
1257 conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status);
1260 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1261 *perr = ntstatus_to_werror(nt_status);
1266 * Save who we are - we are temporarily becoming the connection user.
1271 if (!become_user(conn, conn->vuid)) {
1272 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1278 * make the directories version and version\driver_name
1279 * under the architecture directory.
1281 DEBUG(5,("Creating first directory\n"));
1282 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1283 mkdir_internal(conn, new_dir);
1285 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1286 * listed for this driver which has already been moved, skip it (note:
1287 * drivers may list the same file name several times. Then check if the
1288 * file already exists in archi\cversion\, if so, check that the version
1289 * info (or time stamps if version info is unavailable) is newer (or the
1290 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1291 * Otherwise, delete the file.
1293 * If a file is not moved to archi\cversion\ because of an error, all the
1294 * rest of the 'unmoved' driver files are removed from archi\. If one or
1295 * more of the driver's files was already moved to archi\cversion\, it
1296 * potentially leaves the driver in a partially updated state. Version
1297 * trauma will most likely occur if an client attempts to use any printer
1298 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1299 * done is appropriate... later JRR
1302 DEBUG(5,("Moving files now !\n"));
1304 if (driver->driverpath && strlen(driver->driverpath)) {
1305 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1306 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1307 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1309 status = rename_internals(conn, new_name, old_name, True);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1312 new_name, old_name));
1313 *perr = ntstatus_to_werror(status);
1314 unlink_internals(conn, 0, new_name);
1319 unlink_internals(conn, 0, new_name);
1322 if (driver->datafile && strlen(driver->datafile)) {
1323 if (!strequal(driver->datafile, driver->driverpath)) {
1324 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1325 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1326 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1328 status = rename_internals(conn, new_name, old_name, True);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1331 new_name, old_name));
1332 *perr = ntstatus_to_werror(status);
1333 unlink_internals(conn, 0, new_name);
1338 unlink_internals(conn, 0, new_name);
1342 if (driver->configfile && strlen(driver->configfile)) {
1343 if (!strequal(driver->configfile, driver->driverpath) &&
1344 !strequal(driver->configfile, driver->datafile)) {
1345 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1346 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1347 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1349 status = rename_internals(conn, new_name, old_name, True);
1350 if (!NT_STATUS_IS_OK(status)) {
1351 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1352 new_name, old_name));
1353 *perr = ntstatus_to_werror(status);
1354 unlink_internals(conn, 0, new_name);
1359 unlink_internals(conn, 0, new_name);
1363 if (driver->helpfile && strlen(driver->helpfile)) {
1364 if (!strequal(driver->helpfile, driver->driverpath) &&
1365 !strequal(driver->helpfile, driver->datafile) &&
1366 !strequal(driver->helpfile, driver->configfile)) {
1367 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1368 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1369 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1371 status = rename_internals(conn, new_name, old_name, True);
1372 if (!NT_STATUS_IS_OK(status)) {
1373 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1374 new_name, old_name));
1375 *perr = ntstatus_to_werror(status);
1376 unlink_internals(conn, 0, new_name);
1381 unlink_internals(conn, 0, new_name);
1385 if (driver->dependentfiles) {
1386 for (i=0; *driver->dependentfiles[i]; i++) {
1387 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1388 !strequal(driver->dependentfiles[i], driver->datafile) &&
1389 !strequal(driver->dependentfiles[i], driver->configfile) &&
1390 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1392 for (j=0; j < i; j++) {
1393 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1398 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1399 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1400 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1402 status = rename_internals(conn, new_name, old_name, True);
1403 if (!NT_STATUS_IS_OK(status)) {
1404 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1405 new_name, old_name));
1406 *perr = ntstatus_to_werror(status);
1407 unlink_internals(conn, 0, new_name);
1412 unlink_internals(conn, 0, new_name);
1418 close_cnum(conn, user->vuid);
1421 return ver == -1 ? False : True;
1424 /****************************************************************************
1425 ****************************************************************************/
1426 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1429 fstring architecture;
1435 TDB_DATA kbuf, dbuf;
1437 get_short_archi(architecture, driver->environment);
1439 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1440 * \\server is added in the rpc server layer.
1441 * It does make sense to NOT store the server's name in the printer TDB.
1444 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1446 /* .inf files do not always list a file for each of the four standard files.
1447 * Don't prepend a path to a null filename, or client claims:
1448 * "The server on which the printer resides does not have a suitable
1449 * <printer driver name> printer driver installed. Click OK if you
1450 * wish to install the driver on your local machine."
1452 if (strlen(driver->driverpath)) {
1453 fstrcpy(temp_name, driver->driverpath);
1454 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1457 if (strlen(driver->datafile)) {
1458 fstrcpy(temp_name, driver->datafile);
1459 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1462 if (strlen(driver->configfile)) {
1463 fstrcpy(temp_name, driver->configfile);
1464 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1467 if (strlen(driver->helpfile)) {
1468 fstrcpy(temp_name, driver->helpfile);
1469 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1472 if (driver->dependentfiles) {
1473 for (i=0; *driver->dependentfiles[i]; i++) {
1474 fstrcpy(temp_name, driver->dependentfiles[i]);
1475 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1479 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1481 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1488 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1491 driver->environment,
1496 driver->monitorname,
1497 driver->defaultdatatype);
1499 if (driver->dependentfiles) {
1500 for (i=0; *driver->dependentfiles[i]; i++) {
1501 len += tdb_pack(buf+len, buflen-len, "f",
1502 driver->dependentfiles[i]);
1506 if (len != buflen) {
1509 tb = (char *)Realloc(buf, len);
1511 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1522 kbuf.dsize = strlen(key)+1;
1526 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1530 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1536 /****************************************************************************
1537 ****************************************************************************/
1538 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1540 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1543 info3.cversion = driver->version;
1544 fstrcpy(info3.name,driver->name);
1545 fstrcpy(info3.environment,driver->environment);
1546 fstrcpy(info3.driverpath,driver->driverpath);
1547 fstrcpy(info3.datafile,driver->datafile);
1548 fstrcpy(info3.configfile,driver->configfile);
1549 fstrcpy(info3.helpfile,driver->helpfile);
1550 fstrcpy(info3.monitorname,driver->monitorname);
1551 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1552 info3.dependentfiles = driver->dependentfiles;
1554 return add_a_printer_driver_3(&info3);
1558 /****************************************************************************
1559 ****************************************************************************/
1560 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1562 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1566 fstrcpy(info.name, in_prt);
1567 fstrcpy(info.defaultdatatype, "RAW");
1569 fstrcpy(info.driverpath, "");
1570 fstrcpy(info.datafile, "");
1571 fstrcpy(info.configfile, "");
1572 fstrcpy(info.helpfile, "");
1574 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1577 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1578 fstrcpy(info.dependentfiles[0], "");
1580 *info_ptr = memdup(&info, sizeof(info));
1585 /****************************************************************************
1586 ****************************************************************************/
1587 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1589 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1590 TDB_DATA kbuf, dbuf;
1591 fstring architecture;
1596 ZERO_STRUCT(driver);
1598 get_short_archi(architecture, in_arch);
1600 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1602 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1605 kbuf.dsize = strlen(key)+1;
1607 dbuf = tdb_fetch(tdb_drivers, kbuf);
1609 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1611 if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1613 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1622 driver.defaultdatatype);
1625 while (len < dbuf.dsize) {
1628 tddfs = (fstring *)Realloc(driver.dependentfiles,
1629 sizeof(fstring)*(i+2));
1630 if (tddfs == NULL) {
1631 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1634 else driver.dependentfiles = tddfs;
1636 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1637 &driver.dependentfiles[i]);
1640 if (driver.dependentfiles != NULL)
1641 fstrcpy(driver.dependentfiles[i], "");
1643 SAFE_FREE(dbuf.dptr);
1645 if (len != dbuf.dsize) {
1646 SAFE_FREE(driver.dependentfiles);
1648 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1651 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1656 /****************************************************************************
1657 ****************************************************************************/
1658 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1660 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1666 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1667 DEBUG(10,("driver key: [%s]\n", key));
1670 kbuf.dsize = strlen(key)+1;
1671 if (!tdb_exists(tdb_drivers, kbuf)) return False;
1674 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1676 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1677 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1678 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1679 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1680 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1681 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1682 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1684 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1685 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1686 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1688 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1689 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1690 pstrcat(line, info3->configfile);
1692 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1693 pstrcat(line, info3->datafile);
1695 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1696 pstrcat(line, info3->helpfile);
1698 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1699 pstrcat(line, info3->monitorname);
1701 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1704 for (i=0; info3->dependentfiles &&
1705 *info3->dependentfiles[i]; i++) {
1706 if (i) pstrcat(line, ","); /* don't end in a "," */
1707 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1708 pstrcat(line, info3->dependentfiles[i]);
1716 /****************************************************************************
1717 debugging function, dump at level 6 the struct in the logs
1718 ****************************************************************************/
1719 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1722 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1725 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1731 if (driver.info_3 == NULL)
1734 info3=driver.info_3;
1736 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1737 DEBUGADD(106,("name:[%s]\n", info3->name));
1738 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1739 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1740 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1741 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1742 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1743 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1744 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1746 for (i=0; info3->dependentfiles &&
1747 *info3->dependentfiles[i]; i++) {
1748 DEBUGADD(106,("dependentfile:[%s]\n",
1749 info3->dependentfiles[i]));
1756 DEBUGADD(1,("Level not implemented\n"));
1764 /****************************************************************************
1765 ****************************************************************************/
1766 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1770 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1772 if (!nt_devmode) return len;
1774 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1775 nt_devmode->devicename,
1776 nt_devmode->formname,
1778 nt_devmode->specversion,
1779 nt_devmode->driverversion,
1781 nt_devmode->driverextra,
1782 nt_devmode->orientation,
1783 nt_devmode->papersize,
1784 nt_devmode->paperlength,
1785 nt_devmode->paperwidth,
1788 nt_devmode->defaultsource,
1789 nt_devmode->printquality,
1792 nt_devmode->yresolution,
1793 nt_devmode->ttoption,
1794 nt_devmode->collate,
1795 nt_devmode->logpixels,
1798 nt_devmode->bitsperpel,
1799 nt_devmode->pelswidth,
1800 nt_devmode->pelsheight,
1801 nt_devmode->displayflags,
1802 nt_devmode->displayfrequency,
1803 nt_devmode->icmmethod,
1804 nt_devmode->icmintent,
1805 nt_devmode->mediatype,
1806 nt_devmode->dithertype,
1807 nt_devmode->reserved1,
1808 nt_devmode->reserved2,
1809 nt_devmode->panningwidth,
1810 nt_devmode->panningheight,
1811 nt_devmode->private);
1814 if (nt_devmode->private) {
1815 len += tdb_pack(buf+len, buflen-len, "B",
1816 nt_devmode->driverextra,
1817 nt_devmode->private);
1820 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1825 /****************************************************************************
1826 ****************************************************************************/
1827 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1831 while (param != NULL) {
1832 len += tdb_pack(buf+len, buflen-len, "pfdB",
1841 len += tdb_pack(buf+len, buflen-len, "p", param);
1847 /****************************************************************************
1848 delete a printer - this just deletes the printer info file, any open
1849 handles are not affected
1850 ****************************************************************************/
1851 uint32 del_a_printer(char *sharename)
1856 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1859 kbuf.dsize=strlen(key)+1;
1861 tdb_delete(tdb_printers, kbuf);
1865 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1866 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1867 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1868 /****************************************************************************
1869 ****************************************************************************/
1870 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1876 TDB_DATA kbuf, dbuf;
1879 * in addprinter: no servername and the printer is the name
1880 * in setprinter: servername is \\server
1881 * and printer is \\server\\printer
1883 * Samba manages only local printers.
1884 * we currently don't support things like path=\\other_server\printer
1887 if (info->servername[0]!='\0') {
1888 trim_string(info->printername, info->servername, NULL);
1889 trim_string(info->printername, "\\", NULL);
1890 info->servername[0]='\0';
1894 * JFM: one day I'll forget.
1895 * below that's info->portname because that's the SAMBA sharename
1896 * and I made NT 'thinks' it's the portname
1897 * the info->sharename is the thing you can name when you add a printer
1898 * that's the short-name when you create shared printer for 95/98
1899 * So I've made a limitation in SAMBA: you can only have 1 printer model
1900 * behind a SAMBA share.
1908 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1911 info->default_priority,
1928 info->printprocessor,
1932 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1934 len += pack_specifics(info->specific, buf+len, buflen-len);
1936 if (buflen != len) {
1939 tb = (char *)Realloc(buf, len);
1941 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1951 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1954 kbuf.dsize = strlen(key)+1;
1958 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
1961 if (!W_ERROR_IS_OK(ret))
1962 DEBUG(8, ("error updating printer to tdb on disk\n"));
1966 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1967 info->sharename, info->drivername, info->portname, len));
1973 /****************************************************************************
1974 ****************************************************************************/
1975 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1977 NT_PRINTER_PARAM *current;
1979 DEBUG(108,("add_a_specific_param\n"));
1981 (*param)->next=NULL;
1983 if (info_2->specific == NULL)
1985 info_2->specific=*param;
1989 current=info_2->specific;
1990 while (current->next != NULL) {
1991 current=current->next;
1993 current->next=*param;
1999 /****************************************************************************
2000 ****************************************************************************/
2001 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2003 NT_PRINTER_PARAM *current;
2004 NT_PRINTER_PARAM *previous;
2006 current=info_2->specific;
2009 if (current==NULL) return (False);
2011 if ( !strcmp(current->value, param->value) &&
2012 (strlen(current->value)==strlen(param->value)) ) {
2013 DEBUG(109,("deleting first value\n"));
2014 info_2->specific=current->next;
2015 SAFE_FREE(current->data);
2017 DEBUG(109,("deleted first value\n"));
2021 current=previous->next;
2023 while ( current!=NULL ) {
2024 if (!strcmp(current->value, param->value) &&
2025 strlen(current->value)==strlen(param->value) ) {
2026 DEBUG(109,("deleting current value\n"));
2027 previous->next=current->next;
2028 SAFE_FREE(current->data);
2030 DEBUG(109,("deleted current value\n"));
2034 previous=previous->next;
2035 current=current->next;
2040 /****************************************************************************
2041 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2042 ****************************************************************************/
2043 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2045 NT_PRINTER_PARAM *param = *param_ptr;
2050 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2052 SAFE_FREE(param->data);
2053 SAFE_FREE(*param_ptr);
2056 /****************************************************************************
2057 Malloc and return an NT devicemode.
2058 ****************************************************************************/
2060 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2063 * should I init this ones ???
2064 nt_devmode->devicename
2068 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2070 if (nt_devmode == NULL) {
2071 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2075 ZERO_STRUCTP(nt_devmode);
2077 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2078 fstrcpy(nt_devmode->devicename, adevice);
2080 fstrcpy(nt_devmode->formname, "Letter");
2082 nt_devmode->specversion = 0x0401;
2083 nt_devmode->driverversion = 0x0400;
2084 nt_devmode->size = 0x00DC;
2085 nt_devmode->driverextra = 0x0000;
2086 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2087 DEFAULTSOURCE | COPIES | SCALE |
2088 PAPERSIZE | ORIENTATION;
2089 nt_devmode->orientation = 1;
2090 nt_devmode->papersize = PAPER_LETTER;
2091 nt_devmode->paperlength = 0;
2092 nt_devmode->paperwidth = 0;
2093 nt_devmode->scale = 0x64;
2094 nt_devmode->copies = 01;
2095 nt_devmode->defaultsource = BIN_FORMSOURCE;
2096 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2097 nt_devmode->color = COLOR_MONOCHROME;
2098 nt_devmode->duplex = DUP_SIMPLEX;
2099 nt_devmode->yresolution = 0;
2100 nt_devmode->ttoption = TT_SUBDEV;
2101 nt_devmode->collate = COLLATE_FALSE;
2102 nt_devmode->icmmethod = 0;
2103 nt_devmode->icmintent = 0;
2104 nt_devmode->mediatype = 0;
2105 nt_devmode->dithertype = 0;
2107 /* non utilisés par un driver d'imprimante */
2108 nt_devmode->logpixels = 0;
2109 nt_devmode->bitsperpel = 0;
2110 nt_devmode->pelswidth = 0;
2111 nt_devmode->pelsheight = 0;
2112 nt_devmode->displayflags = 0;
2113 nt_devmode->displayfrequency = 0;
2114 nt_devmode->reserved1 = 0;
2115 nt_devmode->reserved2 = 0;
2116 nt_devmode->panningwidth = 0;
2117 nt_devmode->panningheight = 0;
2119 nt_devmode->private = NULL;
2123 /****************************************************************************
2124 Deepcopy an NT devicemode.
2125 ****************************************************************************/
2127 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2129 NT_DEVICEMODE *new_nt_devicemode = NULL;
2131 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2132 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2136 new_nt_devicemode->private = NULL;
2137 if (nt_devicemode->private != NULL) {
2138 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2139 SAFE_FREE(new_nt_devicemode);
2140 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2145 return new_nt_devicemode;
2148 /****************************************************************************
2149 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2150 ****************************************************************************/
2152 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2154 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2156 if(nt_devmode == NULL)
2159 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2161 SAFE_FREE(nt_devmode->private);
2162 SAFE_FREE(*devmode_ptr);
2165 /****************************************************************************
2166 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2167 ****************************************************************************/
2168 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2170 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2171 NT_PRINTER_PARAM *param_ptr;
2176 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2178 free_nt_devicemode(&info->devmode);
2180 for(param_ptr = info->specific; param_ptr; ) {
2181 NT_PRINTER_PARAM *tofree = param_ptr;
2183 param_ptr = param_ptr->next;
2184 free_nt_printer_param(&tofree);
2187 SAFE_FREE(*info_ptr);
2191 /****************************************************************************
2192 ****************************************************************************/
2193 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2197 NT_DEVICEMODE devmode;
2199 ZERO_STRUCT(devmode);
2201 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2203 if (!*nt_devmode) return len;
2205 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2209 &devmode.specversion,
2210 &devmode.driverversion,
2212 &devmode.driverextra,
2213 &devmode.orientation,
2215 &devmode.paperlength,
2216 &devmode.paperwidth,
2219 &devmode.defaultsource,
2220 &devmode.printquality,
2223 &devmode.yresolution,
2229 &devmode.bitsperpel,
2231 &devmode.pelsheight,
2232 &devmode.displayflags,
2233 &devmode.displayfrequency,
2237 &devmode.dithertype,
2240 &devmode.panningwidth,
2241 &devmode.panningheight,
2244 if (devmode.private) {
2245 /* the len in tdb_unpack is an int value and
2246 * devmode.driverextra is only a short
2248 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2249 devmode.driverextra=(uint16)extra_len;
2251 /* check to catch an invalid TDB entry so we don't segfault */
2252 if (devmode.driverextra == 0) {
2253 devmode.private = NULL;
2257 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2259 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2260 if (devmode.private)
2261 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2266 /****************************************************************************
2267 ****************************************************************************/
2268 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2271 NT_PRINTER_PARAM param, *p;
2276 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2279 len += tdb_unpack(buf+len, buflen-len, "fdB",
2285 *list = memdup(¶m, sizeof(param));
2287 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2293 static void map_to_os2_driver(fstring drivername)
2295 static BOOL initialised=False;
2296 static fstring last_from,last_to;
2297 char *mapfile = lp_os2_driver_map();
2298 char **lines = NULL;
2302 if (!strlen(drivername))
2309 *last_from = *last_to = 0;
2313 if (strequal(drivername,last_from)) {
2314 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2315 fstrcpy(drivername,last_to);
2319 lines = file_lines_load(mapfile, &numlines);
2320 if (numlines == 0) {
2321 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2325 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2327 for( i = 0; i < numlines; i++) {
2328 char *nt_name = lines[i];
2329 char *os2_name = strchr(nt_name,'=');
2336 while (isspace(*nt_name))
2339 if (!*nt_name || strchr("#;",*nt_name))
2343 int l = strlen(nt_name);
2344 while (l && isspace(nt_name[l-1])) {
2350 while (isspace(*os2_name))
2354 int l = strlen(os2_name);
2355 while (l && isspace(os2_name[l-1])) {
2361 if (strequal(nt_name,drivername)) {
2362 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2363 fstrcpy(last_from,drivername);
2364 fstrcpy(last_to,os2_name);
2365 fstrcpy(drivername,os2_name);
2366 file_lines_free(lines);
2371 file_lines_free(lines);
2374 /****************************************************************************
2375 get a default printer info 2 struct
2376 ****************************************************************************/
2377 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2379 extern pstring global_myname;
2381 NT_PRINTER_INFO_LEVEL_2 info;
2385 snum = lp_servicenumber(sharename);
2387 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2388 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2389 global_myname, sharename);
2390 fstrcpy(info.sharename, sharename);
2391 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2392 fstrcpy(info.drivername, lp_printerdriver(snum));
2395 if (!*info.drivername)
2396 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2398 /* by setting the driver name to an empty string, a local NT admin
2399 can now run the **local** APW to install a local printer driver
2400 for a Samba shared printer in 2.2. Without this, drivers **must** be
2401 installed on the Samba server for NT clients --jerry */
2402 if (!*info.drivername)
2403 fstrcpy(info.drivername, "");
2407 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2409 pstrcpy(info.comment, "");
2410 fstrcpy(info.printprocessor, "winprint");
2411 fstrcpy(info.datatype, "RAW");
2413 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2414 | PRINTER_ATTRIBUTE_LOCAL \
2415 | PRINTER_ATTRIBUTE_RAW_ONLY \
2416 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2418 info.starttime = 0; /* Minutes since 12:00am GMT */
2419 info.untiltime = 0; /* Minutes since 12:00am GMT */
2421 info.default_priority = 1;
2422 info.setuptime = (uint32)time(NULL);
2424 #if 1 /* JRA - NO NOT CHANGE ! */
2425 info.devmode = NULL;
2428 * We should not return a default devicemode, as this causes
2429 * Win2K to not send the correct one on PCL drivers. It needs to
2430 * see a null devicemode so it can then overwrite the devicemode
2431 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2433 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2437 /* This will get the current RPC talloc context, but we should be
2438 passing this as a parameter... fixme... JRA ! */
2440 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2443 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2445 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2454 free_nt_devicemode(&info.devmode);
2455 return WERR_ACCESS_DENIED;
2458 /****************************************************************************
2459 ****************************************************************************/
2460 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2463 NT_PRINTER_INFO_LEVEL_2 info;
2465 TDB_DATA kbuf, dbuf;
2466 fstring printername;
2470 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2473 kbuf.dsize = strlen(key)+1;
2475 dbuf = tdb_fetch(tdb_printers, kbuf);
2477 return get_a_printer_2_default(info_ptr, sharename);
2479 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2482 &info.default_priority,
2499 info.printprocessor,
2503 /* Samba has to have shared raw drivers. */
2504 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2506 /* Restore the stripped strings. */
2507 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2508 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2510 fstrcpy(info.printername, printername);
2512 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2513 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2515 /* This will get the current RPC talloc context, but we should be
2516 passing this as a parameter... fixme... JRA ! */
2518 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2520 /* Fix for OS/2 drivers. */
2522 if (get_remote_arch() == RA_OS2)
2523 map_to_os2_driver(info.drivername);
2525 SAFE_FREE(dbuf.dptr);
2526 *info_ptr=memdup(&info, sizeof(info));
2528 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2529 sharename, info.printername, info.drivername));
2534 /****************************************************************************
2535 debugging function, dump at level 6 the struct in the logs
2536 ****************************************************************************/
2537 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2540 NT_PRINTER_INFO_LEVEL_2 *info2;
2542 DEBUG(106,("Dumping printer at level [%d]\n", level));
2548 if (printer.info_2 == NULL)
2552 info2=printer.info_2;
2554 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2555 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2556 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2557 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2558 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2559 DEBUGADD(106,("status:[%s]\n", werror_str(info2->status)));
2560 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2561 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2562 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2563 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2564 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2566 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2567 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2568 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2569 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2570 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2571 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2572 DEBUGADD(106,("location:[%s]\n", info2->location));
2573 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2574 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2575 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2576 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2582 DEBUGADD(1,("Level not implemented\n"));
2590 /****************************************************************************
2591 Get the parameters we can substitute in an NT print job.
2592 ****************************************************************************/
2594 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2596 NT_PRINTER_INFO_LEVEL *printer = NULL;
2598 **printername = **sharename = **portname = '\0';
2600 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2603 fstrcpy(*printername, printer->info_2->printername);
2604 fstrcpy(*sharename, printer->info_2->sharename);
2605 fstrcpy(*portname, printer->info_2->portname);
2607 free_a_printer(&printer, 2);
2611 * The function below are the high level ones.
2612 * only those ones must be called from the spoolss code.
2616 /****************************************************************************
2617 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2618 ****************************************************************************/
2620 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2624 dump_a_printer(printer, level);
2630 printer.info_2->c_setprinter++;
2631 result=update_a_printer_2(printer.info_2);
2635 result=WERR_UNKNOWN_LEVEL;
2642 /****************************************************************************
2643 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2644 We split this out from mod_a_printer as it updates the id's and timestamps.
2645 ****************************************************************************/
2647 WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2651 dump_a_printer(printer, level);
2658 * Update the changestamp.
2659 * Note we must *not* do this in mod_a_printer().
2662 time_t time_unix = time(NULL);
2663 unix_to_nt_time(&time_nt, time_unix);
2664 if (printer.info_2->changeid==time_nt.low)
2665 printer.info_2->changeid++;
2667 printer.info_2->changeid=time_nt.low;
2669 printer.info_2->c_setprinter++;
2671 result=update_a_printer_2(printer.info_2);
2675 result=WERR_UNKNOWN_LEVEL;
2682 /****************************************************************************
2683 Initialize printer devmode & data with previously saved driver init values.
2684 ****************************************************************************/
2685 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2689 TDB_DATA kbuf, dbuf;
2690 NT_PRINTER_PARAM *current;
2691 NT_PRINTER_INFO_LEVEL_2 info;
2695 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2698 kbuf.dsize = strlen(key)+1;
2700 dbuf = tdb_fetch(tdb_drivers, kbuf);
2705 * Get the saved DEVMODE..
2707 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2710 * The saved DEVMODE contains the devicename from the printer used during
2711 * the initialization save. Change it to reflect the new printer.
2713 ZERO_STRUCT(info.devmode->devicename);
2714 fstrcpy(info.devmode->devicename, info_ptr->printername);
2717 * Bind the saved DEVMODE to the new the printer.
2719 free_nt_devicemode(&info_ptr->devmode);
2720 info_ptr->devmode = info.devmode;
2722 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2723 info_ptr->printername, info_ptr->drivername));
2726 * There should not be any printer data 'specifics' already set during the
2727 * add printer operation, if there are delete them.
2729 while ( (current=info_ptr->specific) != NULL ) {
2730 info_ptr->specific=current->next;
2731 SAFE_FREE(current->data);
2736 * Add the printer data 'specifics' to the new printer
2738 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2740 SAFE_FREE(dbuf.dptr);
2745 /****************************************************************************
2746 Initialize printer devmode & data with previously saved driver init values.
2747 When a printer is created using AddPrinter, the drivername bound to the
2748 printer is used to lookup previously saved driver initialization info, which
2749 is bound to the new printer.
2750 ****************************************************************************/
2752 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2760 result=set_driver_init_2(printer->info_2);
2771 /****************************************************************************
2772 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2773 in the tdb. Note: this is different from the driver entry and the printer
2774 entry. There should be a single driver init entry for each driver regardless
2775 of whether it was installed from NT or 2K. Technically, they should be
2776 different, but they work out to the same struct.
2777 ****************************************************************************/
2778 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2782 int buflen, len, ret;
2783 TDB_DATA kbuf, dbuf;
2790 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2792 len += pack_specifics(info->specific, buf+len, buflen-len);
2794 if (buflen != len) {
2797 tb = (char *)Realloc(buf, len);
2799 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2808 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2811 kbuf.dsize = strlen(key)+1;
2815 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2819 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2823 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2824 info->sharename, info->drivername));
2829 /****************************************************************************
2830 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2831 ****************************************************************************/
2833 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2837 dump_a_printer(printer, level);
2843 result=update_driver_init_2(printer.info_2);
2854 /****************************************************************************
2855 Convert the printer data value, a REG_BINARY array, into an initialization
2856 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2857 got to keep the endians happy :).
2858 ****************************************************************************/
2860 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2862 BOOL result = False;
2866 ZERO_STRUCT(devmode);
2868 prs_init(&ps, 0, ctx, UNMARSHALL);
2869 ps.data_p = (char *)param->data;
2870 ps.buffer_size = param->data_len;
2872 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2873 result = convert_devicemode("", &devmode, &nt_devmode);
2875 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2880 /****************************************************************************
2881 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2883 1. Use the driver's config DLL to this UNC printername and:
2884 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2885 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2886 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2888 The last step triggers saving the "driver initialization" information for
2889 this printer into the tdb. Later, new printers that use this driver will
2890 have this initialization information bound to them. This simulates the
2891 driver initialization, as if it had run on the Samba server (as it would
2894 The Win32 client side code requirement sucks! But until we can run arbitrary
2895 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2897 It would have been easier to use SetPrinter because all the UNMARSHALLING of
2898 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2899 about it and you will realize why. JRR 010720
2900 ****************************************************************************/
2902 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2904 WERROR status = WERR_OK;
2905 TALLOC_CTX *ctx = NULL;
2906 NT_DEVICEMODE *nt_devmode = NULL;
2907 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2910 * Set devmode on printer info, so entire printer initialization can be
2913 if ((ctx = talloc_init()) == NULL)
2916 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2917 status = WERR_NOMEM;
2921 ZERO_STRUCTP(nt_devmode);
2924 * The DEVMODE is held in the 'data' component of the param in raw binary.
2925 * Convert it to to a devmode structure
2927 if (!convert_driver_init(param, ctx, nt_devmode)) {
2928 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
2929 status = WERR_INVALID_PARAM;
2934 * Pack up and add (or update) the DEVMODE and any current printer data to
2935 * a 'driver init' element in the tdb
2938 printer->info_2->devmode = nt_devmode;
2939 if (update_driver_init(*printer, 2)!=0) {
2940 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
2941 status = WERR_NOMEM;
2946 * If driver initialization info was successfully saved, set the current
2947 * printer to match it. This allows initialization of the current printer
2948 * as well as the driver.
2950 status = mod_a_printer(*printer, 2);
2951 if (!W_ERROR_IS_OK(status)) {
2952 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
2953 printer->info_2->printername));
2957 talloc_destroy(ctx);
2959 SAFE_FREE(nt_devmode->private);
2960 SAFE_FREE(nt_devmode);
2961 printer->info_2->devmode = tmp_devmode;
2966 /****************************************************************************
2967 Update the driver init info (DEVMODE and specifics) for a printer
2968 ****************************************************************************/
2970 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
2972 WERROR status = WERR_OK;
2978 status=save_driver_init_2(printer, param);
2982 status=WERR_UNKNOWN_LEVEL;
2989 /****************************************************************************
2990 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2991 ****************************************************************************/
2993 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2996 NT_PRINTER_INFO_LEVEL *printer = NULL;
3000 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3006 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3007 DEBUG(0,("get_a_printer: malloc fail.\n"));
3010 ZERO_STRUCTP(printer);
3011 result=get_a_printer_2(&printer->info_2, sharename);
3012 if (W_ERROR_IS_OK(result)) {
3013 dump_a_printer(*printer, level);
3014 *pp_printer = printer;
3021 result=WERR_UNKNOWN_LEVEL;
3025 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, werror_str(result)));
3030 /****************************************************************************
3031 Deletes a NT_PRINTER_INFO_LEVEL struct.
3032 ****************************************************************************/
3034 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3037 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3039 DEBUG(104,("freeing a printer at level [%d]\n", level));
3041 if (printer == NULL)
3048 if (printer->info_2 != NULL)
3050 free_nt_printer_info_level_2(&printer->info_2);
3064 SAFE_FREE(*pp_printer);
3068 /****************************************************************************
3069 ****************************************************************************/
3070 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3073 DEBUG(104,("adding a printer at level [%d]\n", level));
3074 dump_a_printer_driver(driver, level);
3080 result=add_a_printer_driver_3(driver.info_3);
3086 result=add_a_printer_driver_6(driver.info_6);
3096 /****************************************************************************
3097 ****************************************************************************/
3098 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3099 fstring printername, fstring architecture, uint32 version)
3107 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3115 if (W_ERROR_IS_OK(result))
3116 dump_a_printer_driver(*driver, level);
3120 /****************************************************************************
3121 ****************************************************************************/
3122 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3130 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3131 if (driver.info_3 != NULL)
3133 info3=driver.info_3;
3134 SAFE_FREE(info3->dependentfiles);
3135 ZERO_STRUCTP(info3);
3147 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3148 if (driver.info_6 != NULL)
3150 info6=driver.info_6;
3151 SAFE_FREE(info6->dependentfiles);
3152 SAFE_FREE(info6->previousnames);
3153 ZERO_STRUCTP(info6);
3171 /****************************************************************************
3172 Determine whether or not a particular driver is currently assigned
3174 ****************************************************************************/
3175 BOOL printer_driver_in_use (char *arch, char *driver)
3177 TDB_DATA kbuf, newkey, dbuf;
3178 NT_PRINTER_INFO_LEVEL_2 info;
3182 if (!nt_printing_init())
3185 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3187 /* loop through the printers.tdb and check for the drivername */
3188 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3189 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3192 dbuf = tdb_fetch(tdb_printers, kbuf);
3196 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3199 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3202 &info.default_priority,
3219 info.printprocessor,
3223 SAFE_FREE(dbuf.dptr);
3226 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3231 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3232 info.printername, info.drivername));
3234 if (strcmp(info.drivername, driver) == 0)
3236 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3237 info.printername, driver));
3241 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3245 /* report that the driver is in use by default */
3249 /****************************************************************************
3250 Remove a printer driver from the TDB. This assumes that the the driver was
3251 previously looked up.
3252 ***************************************************************************/
3253 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3260 get_short_archi(arch, i->environment);
3261 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3262 arch, i->cversion, i->name);
3263 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3266 kbuf.dsize=strlen(key)+1;
3268 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3269 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3270 return WERR_ACCESS_DENIED;
3273 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3278 /****************************************************************************
3279 ****************************************************************************/
3280 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3281 fstring value, uint8 **data, uint32 *type, uint32 *len)
3283 /* right now that's enough ! */
3284 NT_PRINTER_PARAM *param;
3287 param=printer.info_2->specific;
3289 while (param != NULL && i < param_index) {
3297 /* exited because it exist */
3299 StrnCpy(value, param->value, sizeof(fstring)-1);
3300 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3303 ZERO_STRUCTP(*data);
3304 memcpy(*data, param->data, param->data_len);
3305 *len=param->data_len;
3309 /****************************************************************************
3310 ****************************************************************************/
3311 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3312 fstring value, uint8 **data, uint32 *type, uint32 *len)
3314 /* right now that's enough ! */
3315 NT_PRINTER_PARAM *param;
3317 DEBUG(10, ("get_specific_param\n"));
3319 param=printer.info_2->specific;
3321 while (param != NULL)
3323 #if 1 /* JRA - I think this should be case insensitive.... */
3324 if ( strequal(value, param->value)
3326 if ( !strcmp(value, param->value)
3328 && strlen(value)==strlen(param->value))
3336 DEBUGADD(10, ("get_specific_param: found one param\n"));
3337 /* exited because it exist */
3340 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3343 memcpy(*data, param->data, param->data_len);
3344 *len=param->data_len;
3346 DEBUGADD(10, ("get_specific_param: exit true\n"));
3349 DEBUGADD(10, ("get_specific_param: exit false\n"));
3353 /****************************************************************************
3354 Store a security desc for a printer.
3355 ****************************************************************************/
3357 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3359 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3360 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3362 TALLOC_CTX *mem_ctx = NULL;
3366 mem_ctx = talloc_init();
3367 if (mem_ctx == NULL)
3370 /* The old owner and group sids of the security descriptor are not
3371 present when new ACEs are added or removed by changing printer
3372 permissions through NT. If they are NULL in the new security
3373 descriptor then copy them over from the old one. */
3375 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3376 DOM_SID *owner_sid, *group_sid;
3377 SEC_ACL *dacl, *sacl;
3378 SEC_DESC *psd = NULL;
3381 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3383 /* Pick out correct owner and group sids */
3385 owner_sid = secdesc_ctr->sec->owner_sid ?
3386 secdesc_ctr->sec->owner_sid :
3387 old_secdesc_ctr->sec->owner_sid;
3389 group_sid = secdesc_ctr->sec->grp_sid ?
3390 secdesc_ctr->sec->grp_sid :
3391 old_secdesc_ctr->sec->grp_sid;
3393 dacl = secdesc_ctr->sec->dacl ?
3394 secdesc_ctr->sec->dacl :
3395 old_secdesc_ctr->sec->dacl;
3397 sacl = secdesc_ctr->sec->sacl ?
3398 secdesc_ctr->sec->sacl :
3399 old_secdesc_ctr->sec->sacl;
3401 /* Make a deep copy of the security descriptor */
3403 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3404 owner_sid, group_sid,
3409 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3412 if (!new_secdesc_ctr) {
3413 new_secdesc_ctr = secdesc_ctr;
3416 /* Store the security descriptor in a tdb */
3418 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3419 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3421 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3423 status = WERR_BADFUNC;
3427 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3429 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3432 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3433 status = WERR_BADFUNC;
3436 /* Free malloc'ed memory */
3442 talloc_destroy(mem_ctx);
3446 /****************************************************************************
3447 Construct a default security descriptor buffer for a printer.
3448 ****************************************************************************/
3450 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3454 SEC_ACL *psa = NULL;
3455 SEC_DESC_BUF *sdb = NULL;
3456 SEC_DESC *psd = NULL;
3459 enum SID_NAME_USE name_type;
3461 /* Create an ACE where Everyone is allowed to print */
3463 init_sec_access(&sa, PRINTER_ACE_PRINT);
3464 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3465 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3467 /* Make the security descriptor owned by the Administrators group
3468 on the PDC of the domain. */
3470 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3471 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3475 /* Backup plan - make printer owned by admins or root.
3476 This should emulate a lanman printer as security
3477 settings can't be changed. */
3479 sid_peek_rid(&owner_sid, &owner_rid);
3481 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3482 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3483 owner_rid != DOMAIN_USER_RID_ADMIN &&
3484 !lookup_name("root", &owner_sid, &name_type)) {
3485 sid_copy(&owner_sid, &global_sid_World);
3489 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3490 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3491 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3492 SEC_ACE_FLAG_INHERIT_ONLY);
3494 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3495 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3496 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3498 /* The ACL revision number in rpc_secdesc.h differs from the one
3499 created by NT when setting ACE entries in printer
3500 descriptors. NT4 complains about the property being edited by a
3503 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3504 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3506 NULL, psa, &sd_size);
3510 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3514 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3516 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3517 (unsigned int)sd_size));
3522 /****************************************************************************
3523 Get a security desc for a printer.
3524 ****************************************************************************/
3526 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3532 if ((temp = strchr(printername + 2, '\\'))) {
3533 printername = temp + 1;
3536 /* Fetch security descriptor from tdb */
3538 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3540 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3541 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3543 DEBUG(4,("using default secdesc for %s\n", printername));
3545 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3552 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3553 this security descriptor has been created when winbindd was
3554 down. Take ownership of security descriptor. */
3556 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3558 enum SID_NAME_USE name_type;
3560 /* Change sd owner to workgroup administrator */
3562 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3564 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3565 SEC_DESC *psd = NULL;
3570 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3572 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3574 (*secdesc_ctr)->sec->grp_sid,
3575 (*secdesc_ctr)->sec->sacl,
3576 (*secdesc_ctr)->sec->dacl,
3579 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3581 /* Swap with other one */
3583 *secdesc_ctr = new_secdesc_ctr;
3587 nt_printing_setsec(printername, *secdesc_ctr);
3591 if (DEBUGLEVEL >= 10) {
3592 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3595 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3596 printername, the_acl->num_aces));
3598 for (i = 0; i < the_acl->num_aces; i++) {
3601 sid_to_string(sid_str, &the_acl->ace[i].sid);
3603 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3604 the_acl->ace[i].type, the_acl->ace[i].flags,
3605 the_acl->ace[i].info.mask));
3615 1: level not implemented
3616 2: file doesn't exist
3617 3: can't allocate memory
3618 4: can't free memory
3619 5: non existant struct
3623 A printer and a printer driver are 2 different things.
3624 NT manages them separatelly, Samba does the same.
3625 Why ? Simply because it's easier and it makes sense !
3627 Now explanation: You have 3 printers behind your samba server,
3628 2 of them are the same make and model (laser A and B). But laser B
3629 has an 3000 sheet feeder and laser A doesn't such an option.
3630 Your third printer is an old dot-matrix model for the accounting :-).
3632 If the /usr/local/samba/lib directory (default dir), you will have
3633 5 files to describe all of this.
3635 3 files for the printers (1 by printer):
3638 NTprinter_accounting
3639 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3640 NTdriver_printer model X
3641 NTdriver_printer model Y
3643 jfm: I should use this comment for the text file to explain
3644 same thing for the forms BTW.
3645 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3649 /* Convert generic access rights to printer object specific access rights.
3650 It turns out that NT4 security descriptors use generic access rights and
3651 NT5 the object specific ones. */
3653 void map_printer_permissions(SEC_DESC *sd)
3657 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3658 se_map_generic(&sd->dacl->ace[i].info.mask,
3659 &printer_generic_mapping);
3663 /****************************************************************************
3664 Check a user has permissions to perform the given operation. We use the
3665 permission constants defined in include/rpc_spoolss.h to check the various
3666 actions we perform when checking printer access.
3668 PRINTER_ACCESS_ADMINISTER:
3669 print_queue_pause, print_queue_resume, update_printer_sec,
3670 update_printer, spoolss_addprinterex_level_2,
3671 _spoolss_setprinterdata
3676 JOB_ACCESS_ADMINISTER:
3677 print_job_delete, print_job_pause, print_job_resume,
3680 ****************************************************************************/
3681 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3683 SEC_DESC_BUF *secdesc = NULL;
3684 uint32 access_granted;
3688 TALLOC_CTX *mem_ctx = NULL;
3689 extern struct current_user current_user;
3691 /* If user is NULL then use the current_user structure */
3694 user = ¤t_user;
3696 /* Always allow root or printer admins to do anything */
3698 if (user->uid == 0 ||
3699 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3703 /* Get printer name */
3705 pname = PRINTERNAME(snum);
3707 if (!pname || !*pname) {
3712 /* Get printer security descriptor */
3714 if(!(mem_ctx = talloc_init())) {
3719 nt_printing_getsec(mem_ctx, pname, &secdesc);
3721 if (access_type == JOB_ACCESS_ADMINISTER) {
3722 SEC_DESC_BUF *parent_secdesc = secdesc;
3724 /* Create a child security descriptor to check permissions
3725 against. This is because print jobs are child objects
3726 objects of a printer. */
3728 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3730 /* Now this is the bit that really confuses me. The access
3731 type needs to be changed from JOB_ACCESS_ADMINISTER to
3732 PRINTER_ACCESS_ADMINISTER for this to work. Something
3733 to do with the child (job) object becoming like a
3736 access_type = PRINTER_ACCESS_ADMINISTER;
3741 map_printer_permissions(secdesc->sec);
3743 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
3744 &access_granted, &status);
3746 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3748 talloc_destroy(mem_ctx);
3756 /****************************************************************************
3757 Check the time parameters allow a print operation.
3758 *****************************************************************************/
3760 BOOL print_time_access_check(int snum)
3762 NT_PRINTER_INFO_LEVEL *printer = NULL;
3764 time_t now = time(NULL);
3768 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3771 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3775 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3777 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3780 free_a_printer(&printer, 2);
3788 /****************************************************************************
3789 Attempt to write a default device.
3790 *****************************************************************************/
3792 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3794 NT_PRINTER_INFO_LEVEL *printer = NULL;
3798 * Don't bother if no default devicemode was sent.
3801 if (printer_default->devmode_cont.devmode == NULL)
3804 result = get_a_printer(&printer, 2, lp_servicename(snum));
3805 if (!W_ERROR_IS_OK(result)) return result;
3808 * Just ignore it if we already have a devmode.
3811 if (printer->info_2->devmode != NULL)
3815 * We don't have a devicemode and we're trying to write
3816 * one. Check we have the access needed.
3818 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3820 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3821 PRINTER_ACCESS_ADMINISTER) {
3822 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3823 result = WERR_ACCESS_DENIED;
3827 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3828 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3829 lp_servicename(snum) ));
3830 result = WERR_ACCESS_DENIED;
3831 /*result = NT_STATUS_NO_PROBLEMO;*/
3835 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3838 * Convert the on the wire devicemode format to the internal one.
3841 if (!convert_devicemode(printer->info_2->printername,
3842 printer_default->devmode_cont.devmode,
3843 &printer->info_2->devmode)) {
3844 result = WERR_NOMEM;
3849 * Finally write back to the tdb.
3852 result = add_a_printer(*printer, 2);
3856 free_a_printer(&printer, 2);