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 DOM_SID global_sid_World;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
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_3(void)
179 TDB_DATA kbuf, newkey, dbuf;
181 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\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_3:moving form\n"));
190 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
191 DEBUG(0,("upgrade_to_version_3: 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_3: 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_3:moving printer\n"));
202 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
203 DEBUG(0,("upgrade_to_version_3: 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_3: 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_3:moving secdesc\n"));
214 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
215 DEBUG(0,("upgrade_to_version_3: 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_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
224 SAFE_FREE(dbuf.dptr);
230 /****************************************************************************
231 Open the NT printing tdb.
232 ****************************************************************************/
234 BOOL nt_printing_init(void)
236 static pid_t local_pid;
237 char *vstring = "INFO/version";
239 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
242 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
244 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
245 lock_path("ntdrivers.tdb"), strerror(errno) ));
249 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
251 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
252 lock_path("ntprinters.tdb"), strerror(errno) ));
256 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
258 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
259 lock_path("ntforms.tdb"), strerror(errno) ));
263 local_pid = sys_getpid();
265 /* handle a Samba upgrade */
266 tdb_lock_bystring(tdb_drivers, vstring);
270 /* Cope with byte-reversed older versions of the db. */
271 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
272 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
273 /* Written on a bigendian machine with old fetch_int code. Save as le. */
274 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
275 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
276 vers_id = NTDRIVERS_DATABASE_VERSION;
279 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
281 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
282 if (!upgrade_to_version_3())
285 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
287 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
290 tdb_unlock_bystring(tdb_drivers, vstring);
295 /****************************************************************************
296 get builtin form struct list
297 ****************************************************************************/
298 int get_builtin_ntforms(nt_forms_struct **list)
300 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
301 return sizeof(default_forms) / sizeof(default_forms[0]);
304 /****************************************************************************
305 get a builtin form struct
306 ****************************************************************************/
308 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
312 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
313 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
314 count = sizeof(default_forms) / sizeof(default_forms[0]);
315 for (i=0;i<count;i++) {
316 if (strequal(form_name,default_forms[i].name)) {
317 DEBUGADD(6,("Found builtin form %s \n", form_name));
318 memcpy(form,&default_forms[i],sizeof(*form));
326 /****************************************************************************
327 get a form struct list
328 ****************************************************************************/
329 int get_ntforms(nt_forms_struct **list)
331 TDB_DATA kbuf, newkey, dbuf;
333 nt_forms_struct form;
338 for (kbuf = tdb_firstkey(tdb_forms);
340 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
341 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
343 dbuf = tdb_fetch(tdb_forms, kbuf);
344 if (!dbuf.dptr) continue;
346 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
347 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
348 &i, &form.flag, &form.width, &form.length, &form.left,
349 &form.top, &form.right, &form.bottom);
350 SAFE_FREE(dbuf.dptr);
351 if (ret != dbuf.dsize) continue;
353 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
355 DEBUG(0,("get_ntforms: Realloc fail.\n"));
367 /****************************************************************************
368 write a form struct list
369 ****************************************************************************/
370 int write_ntforms(nt_forms_struct **list, int number)
377 for (i=0;i<number;i++) {
378 /* save index, so list is rebuilt in correct order */
379 len = tdb_pack(buf, sizeof(buf), "dddddddd",
380 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
381 (*list)[i].left, (*list)[i].top, (*list)[i].right,
383 if (len > sizeof(buf)) break;
384 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
385 kbuf.dsize = strlen(key)+1;
389 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
395 /****************************************************************************
396 add a form struct at the end of the list
397 ****************************************************************************/
398 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
406 * NT tries to add forms even when
407 * they are already in the base
408 * only update the values if already present
413 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
414 for (n=0; n<*count; n++) {
415 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
416 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
423 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
424 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
428 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
432 (*list)[n].flag=form->flags;
433 (*list)[n].width=form->size_x;
434 (*list)[n].length=form->size_y;
435 (*list)[n].left=form->left;
436 (*list)[n].top=form->top;
437 (*list)[n].right=form->right;
438 (*list)[n].bottom=form->bottom;
443 /****************************************************************************
444 delete a named form struct
445 ****************************************************************************/
446 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
455 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
457 for (n=0; n<*count; n++) {
458 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
459 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
465 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
466 *ret = WERR_INVALID_PARAM;
470 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
471 kbuf.dsize = strlen(key)+1;
473 if (tdb_delete(tdb_forms, kbuf) != 0) {
481 /****************************************************************************
483 ****************************************************************************/
484 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
488 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
490 DEBUG(106, ("[%s]\n", form_name));
491 for (n=0; n<count; n++)
493 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
494 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
498 if (n==count) return;
500 (*list)[n].flag=form->flags;
501 (*list)[n].width=form->size_x;
502 (*list)[n].length=form->size_y;
503 (*list)[n].left=form->left;
504 (*list)[n].top=form->top;
505 (*list)[n].right=form->right;
506 (*list)[n].bottom=form->bottom;
509 /****************************************************************************
510 get the nt drivers list
512 traverse the database and look-up the matching names
513 ****************************************************************************/
514 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
520 TDB_DATA kbuf, newkey;
522 get_short_archi(short_archi, architecture);
523 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
525 for (kbuf = tdb_firstkey(tdb_drivers);
527 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
528 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
530 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
531 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
536 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
543 /****************************************************************************
544 function to do the mapping between the long architecture name and
546 ****************************************************************************/
547 BOOL get_short_archi(char *short_archi, char *long_archi)
554 struct table archi_table[]=
556 {"Windows 4.0", "WIN40" },
557 {"Windows NT x86", "W32X86" },
558 {"Windows NT R4000", "W32MIPS" },
559 {"Windows NT Alpha_AXP", "W32ALPHA" },
560 {"Windows NT PowerPC", "W32PPC" },
566 DEBUG(107,("Getting architecture dependant directory\n"));
569 } while ( (archi_table[i].long_archi!=NULL ) &&
570 StrCaseCmp(long_archi, archi_table[i].long_archi) );
572 if (archi_table[i].long_archi==NULL) {
573 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
577 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
579 DEBUGADD(108,("index: [%d]\n", i));
580 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
581 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
586 /****************************************************************************
587 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
588 There are two case to be covered here: PE (Portable Executable) and NE (New
589 Executable) files. Both files support the same INFO structure, but PE files
590 store the signature in unicode, and NE files store it as !unicode.
591 returns -1 on error, 1 on version info found, and 0 on no version info found.
592 ****************************************************************************/
594 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
600 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
601 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
602 fname, PE_HEADER_SIZE));
606 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
607 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
608 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
610 goto no_version_info;
613 /* Is this really a DOS header? */
614 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
615 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
616 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
617 goto no_version_info;
620 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
621 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
622 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
624 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
625 goto no_version_info;
628 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
629 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
631 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
632 goto no_version_info;
635 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
636 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
638 int section_table_bytes;
640 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
641 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
642 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
643 /* At this point, we assume the file is in error. It still could be somthing
644 * else besides a PE file, but it unlikely at this point.
649 /* get the section table */
650 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
651 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
653 if ((buf=malloc(section_table_bytes)) == NULL) {
654 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
655 fname, section_table_bytes));
659 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
660 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
665 /* Iterate the section table looking for the resource section ".rsrc" */
666 for (i = 0; i < num_sections; i++) {
667 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
669 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
670 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
671 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
674 if ((buf=malloc(section_bytes)) == NULL) {
675 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
676 fname, section_bytes));
680 /* Seek to the start of the .rsrc section info */
681 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
682 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
687 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
688 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
693 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
694 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
695 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
696 /* Align to next long address */
697 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
699 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
700 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
701 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
703 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
704 fname, *major, *minor,
705 (*major>>16)&0xffff, *major&0xffff,
706 (*minor>>16)&0xffff, *minor&0xffff));
715 /* Version info not found, fall back to origin date/time */
716 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
720 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
721 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
722 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
723 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
724 /* At this point, we assume the file is in error. It still could be somthing
725 * else besides a NE file, but it unlikely at this point. */
729 /* Allocate a bit more space to speed up things */
731 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
732 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
733 fname, PE_HEADER_SIZE));
737 /* This is a HACK! I got tired of trying to sort through the messy
738 * 'NE' file format. If anyone wants to clean this up please have at
739 * it, but this works. 'NE' files will eventually fade away. JRR */
740 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
741 /* Cover case that should not occur in a well formed 'NE' .dll file */
742 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
744 for(i=0; i<byte_count; i++) {
745 /* Fast skip past data that can't possibly match */
746 if (buf[i] != 'V') continue;
748 /* Potential match data crosses buf boundry, move it to beginning
749 * of buf, and fill the buf with as much as it will hold. */
750 if (i>byte_count-VS_VERSION_INFO_SIZE) {
753 memcpy(buf, &buf[i], byte_count-i);
754 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
755 (byte_count-i))) < 0) {
757 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
762 byte_count = bc + (byte_count - i);
763 if (byte_count<VS_VERSION_INFO_SIZE) break;
768 /* Check that the full signature string and the magic number that
769 * follows exist (not a perfect solution, but the chances that this
770 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
771 * twice, as it is simpler to read the code. */
772 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
773 /* Compute skip alignment to next long address */
774 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
775 sizeof(VS_SIGNATURE)) & 3;
776 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
778 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
779 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
780 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
781 fname, *major, *minor,
782 (*major>>16)&0xffff, *major&0xffff,
783 (*minor>>16)&0xffff, *minor&0xffff));
790 /* Version info not found, fall back to origin date/time */
791 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
796 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
797 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
798 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
809 /****************************************************************************
810 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
811 share one or more files. During the MS installation process files are checked
812 to insure that only a newer version of a shared file is installed over an
813 older version. There are several possibilities for this comparison. If there
814 is no previous version, the new one is newer (obviously). If either file is
815 missing the version info structure, compare the creation date (on Unix use
816 the modification date). Otherwise chose the numerically larger version number.
817 ****************************************************************************/
818 static int file_version_is_newer(connection_struct *conn, fstring new_file,
821 BOOL use_version = True;
826 time_t new_create_time;
830 time_t old_create_time;
834 files_struct *fsp = NULL;
836 SMB_STRUCT_STAT stat_buf;
840 ZERO_STRUCT(stat_buf);
841 new_create_time = (time_t)0;
842 old_create_time = (time_t)0;
844 /* Get file version info (if available) for previous file (if it exists) */
845 pstrcpy(filepath, old_file);
847 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
849 fsp = open_file_shared(conn, filepath, &stat_buf,
850 SET_OPEN_MODE(DOS_OPEN_RDONLY),
851 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
852 0, 0, &access_mode, &action);
854 /* Old file not found, so by definition new file is in fact newer */
855 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
860 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
861 if (ret == -1) goto error_exit;
864 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
867 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
868 old_create_time = st.st_mtime;
869 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
872 close_file(fsp, True);
874 /* Get file version info (if available) for new file */
875 pstrcpy(filepath, new_file);
876 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
878 fsp = open_file_shared(conn, filepath, &stat_buf,
879 SET_OPEN_MODE(DOS_OPEN_RDONLY),
880 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
881 0, 0, &access_mode, &action);
883 /* New file not found, this shouldn't occur if the caller did its job */
884 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
889 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
890 if (ret == -1) goto error_exit;
893 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
896 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
897 new_create_time = st.st_mtime;
898 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
901 close_file(fsp, True);
904 /* Compare versions and choose the larger version number */
905 if (new_major > old_major ||
906 (new_major == old_major && new_minor > old_minor)) {
908 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
912 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
917 /* Compare modification time/dates and choose the newest time/date */
918 if (new_create_time > old_create_time) {
919 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
923 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
930 close_file(fsp, True);
934 /****************************************************************************
935 Determine the correct cVersion associated with an architecture and driver
936 ****************************************************************************/
937 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
938 struct current_user *user, WERROR *perr)
946 files_struct *fsp = NULL;
949 connection_struct *conn;
953 *perr = WERR_INVALID_PARAM;
955 /* If architecture is Windows 95/98/ME, the version is always 0. */
956 if (strcmp(architecture, "WIN40") == 0) {
957 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
962 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
963 /* Null password is ok - we are already an authenticated user... */
964 null_pw = data_blob(NULL, 0);
967 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
971 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
972 *perr = ntstatus_to_werror(nt_status);
976 /* We are temporarily becoming the connection user. */
977 if (!become_user(conn, conn->vuid)) {
978 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
979 *perr = WERR_ACCESS_DENIED;
983 /* Open the driver file (Portable Executable format) and determine the
984 * deriver the cversion. */
985 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
987 unix_convert(driverpath,conn,NULL,&bad_path,&st);
989 fsp = open_file_shared(conn, driverpath, &st,
990 SET_OPEN_MODE(DOS_OPEN_RDONLY),
991 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
992 0, 0, &access_mode, &action);
994 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
996 *perr = WERR_ACCESS_DENIED;
1002 int ret = get_file_version(fsp, driverpath, &major, &minor);
1003 if (ret == -1) goto error_exit;
1006 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1011 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1012 * for more details. Version in this case is not just the version of the
1013 * file, but the version in the sense of kernal mode (2) vs. user mode
1014 * (3) drivers. Other bits of the version fields are the version info.
1017 cversion = major & 0x0000ffff;
1019 case 2: /* WinNT drivers */
1020 case 3: /* Win2K drivers */
1024 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1025 driverpath, cversion));
1029 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1030 driverpath, major, minor));
1033 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1034 driverpath, cversion));
1036 close_file(fsp, True);
1037 close_cnum(conn, user->vuid);
1045 close_file(fsp, True);
1047 close_cnum(conn, user->vuid);
1052 /****************************************************************************
1053 ****************************************************************************/
1054 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1055 struct current_user *user)
1057 fstring architecture;
1063 /* clean up the driver name.
1064 * we can get .\driver.dll
1065 * or worse c:\windows\system\driver.dll !
1067 /* using an intermediate string to not have overlaping memcpy()'s */
1068 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1069 fstrcpy(new_name, p+1);
1070 fstrcpy(driver->driverpath, new_name);
1073 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1074 fstrcpy(new_name, p+1);
1075 fstrcpy(driver->datafile, new_name);
1078 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1079 fstrcpy(new_name, p+1);
1080 fstrcpy(driver->configfile, new_name);
1083 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1084 fstrcpy(new_name, p+1);
1085 fstrcpy(driver->helpfile, new_name);
1088 if (driver->dependentfiles) {
1089 for (i=0; *driver->dependentfiles[i]; i++) {
1090 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1091 fstrcpy(new_name, p+1);
1092 fstrcpy(driver->dependentfiles[i], new_name);
1097 get_short_archi(architecture, driver->environment);
1099 /* jfm:7/16/2000 the client always sends the cversion=0.
1100 * The server should check which version the driver is by reading
1101 * the PE header of driver->driverpath.
1103 * For Windows 95/98 the version is 0 (so the value sent is correct)
1104 * For Windows NT (the architecture doesn't matter)
1105 * NT 3.1: cversion=0
1106 * NT 3.5/3.51: cversion=1
1110 if ((driver->cversion = get_correct_cversion( architecture,
1111 driver->driverpath, user, &err)) == -1)
1117 /****************************************************************************
1118 ****************************************************************************/
1119 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1120 struct current_user *user)
1122 fstring architecture;
1128 /* clean up the driver name.
1129 * we can get .\driver.dll
1130 * or worse c:\windows\system\driver.dll !
1132 /* using an intermediate string to not have overlaping memcpy()'s */
1133 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1134 fstrcpy(new_name, p+1);
1135 fstrcpy(driver->driverpath, new_name);
1138 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1139 fstrcpy(new_name, p+1);
1140 fstrcpy(driver->datafile, new_name);
1143 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1144 fstrcpy(new_name, p+1);
1145 fstrcpy(driver->configfile, new_name);
1148 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1149 fstrcpy(new_name, p+1);
1150 fstrcpy(driver->helpfile, new_name);
1153 if (driver->dependentfiles) {
1154 for (i=0; *driver->dependentfiles[i]; i++) {
1155 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1156 fstrcpy(new_name, p+1);
1157 fstrcpy(driver->dependentfiles[i], new_name);
1162 get_short_archi(architecture, driver->environment);
1164 /* jfm:7/16/2000 the client always sends the cversion=0.
1165 * The server should check which version the driver is by reading
1166 * the PE header of driver->driverpath.
1168 * For Windows 95/98 the version is 0 (so the value sent is correct)
1169 * For Windows NT (the architecture doesn't matter)
1170 * NT 3.1: cversion=0
1171 * NT 3.5/3.51: cversion=1
1175 if ((driver->version = get_correct_cversion(architecture,
1176 driver->driverpath, user, &err)) == -1)
1182 /****************************************************************************
1183 ****************************************************************************/
1184 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1185 uint32 level, struct current_user *user)
1190 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1191 driver=driver_abstract.info_3;
1192 return clean_up_driver_struct_level_3(driver, user);
1196 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1197 driver=driver_abstract.info_6;
1198 return clean_up_driver_struct_level_6(driver, user);
1201 return WERR_INVALID_PARAM;
1205 /****************************************************************************
1206 This function sucks and should be replaced. JRA.
1207 ****************************************************************************/
1209 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1211 dst->cversion = src->version;
1213 fstrcpy( dst->name, src->name);
1214 fstrcpy( dst->environment, src->environment);
1215 fstrcpy( dst->driverpath, src->driverpath);
1216 fstrcpy( dst->datafile, src->datafile);
1217 fstrcpy( dst->configfile, src->configfile);
1218 fstrcpy( dst->helpfile, src->helpfile);
1219 fstrcpy( dst->monitorname, src->monitorname);
1220 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1221 dst->dependentfiles = src->dependentfiles;
1224 #if 0 /* Debugging function */
1226 static char* ffmt(unsigned char *c){
1228 static char ffmt_str[17];
1230 for (i=0; i<16; i++) {
1231 if ((c[i] < ' ') || (c[i] > '~'))
1242 /****************************************************************************
1243 ****************************************************************************/
1244 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1245 struct current_user *user, WERROR *perr)
1247 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1248 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1249 fstring architecture;
1254 connection_struct *conn;
1262 driver=driver_abstract.info_3;
1263 else if (level==6) {
1264 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1265 driver = &converted_driver;
1267 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1271 get_short_archi(architecture, driver->environment);
1273 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1274 /* Null password is ok - we are already an authenticated user... */
1275 null_pw = data_blob(NULL, 0);
1276 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
1279 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1280 *perr = ntstatus_to_werror(nt_status);
1285 * Save who we are - we are temporarily becoming the connection user.
1290 if (!become_user(conn, conn->vuid)) {
1291 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1297 * make the directories version and version\driver_name
1298 * under the architecture directory.
1300 DEBUG(5,("Creating first directory\n"));
1301 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1302 mkdir_internal(conn, new_dir);
1304 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1305 * listed for this driver which has already been moved, skip it (note:
1306 * drivers may list the same file name several times. Then check if the
1307 * file already exists in archi\cversion\, if so, check that the version
1308 * info (or time stamps if version info is unavailable) is newer (or the
1309 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1310 * Otherwise, delete the file.
1312 * If a file is not moved to archi\cversion\ because of an error, all the
1313 * rest of the 'unmoved' driver files are removed from archi\. If one or
1314 * more of the driver's files was already moved to archi\cversion\, it
1315 * potentially leaves the driver in a partially updated state. Version
1316 * trauma will most likely occur if an client attempts to use any printer
1317 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1318 * done is appropriate... later JRR
1321 DEBUG(5,("Moving files now !\n"));
1323 if (driver->driverpath && strlen(driver->driverpath)) {
1324 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1325 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
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);
1341 if (driver->datafile && strlen(driver->datafile)) {
1342 if (!strequal(driver->datafile, driver->driverpath)) {
1343 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1344 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1345 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1347 status = rename_internals(conn, new_name, old_name, True);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1350 new_name, old_name));
1351 *perr = ntstatus_to_werror(status);
1352 unlink_internals(conn, 0, new_name);
1357 unlink_internals(conn, 0, new_name);
1361 if (driver->configfile && strlen(driver->configfile)) {
1362 if (!strequal(driver->configfile, driver->driverpath) &&
1363 !strequal(driver->configfile, driver->datafile)) {
1364 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1365 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1366 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1368 status = rename_internals(conn, new_name, old_name, True);
1369 if (!NT_STATUS_IS_OK(status)) {
1370 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1371 new_name, old_name));
1372 *perr = ntstatus_to_werror(status);
1373 unlink_internals(conn, 0, new_name);
1378 unlink_internals(conn, 0, new_name);
1382 if (driver->helpfile && strlen(driver->helpfile)) {
1383 if (!strequal(driver->helpfile, driver->driverpath) &&
1384 !strequal(driver->helpfile, driver->datafile) &&
1385 !strequal(driver->helpfile, driver->configfile)) {
1386 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1387 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1388 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1390 status = rename_internals(conn, new_name, old_name, True);
1391 if (!NT_STATUS_IS_OK(status)) {
1392 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1393 new_name, old_name));
1394 *perr = ntstatus_to_werror(status);
1395 unlink_internals(conn, 0, new_name);
1400 unlink_internals(conn, 0, new_name);
1404 if (driver->dependentfiles) {
1405 for (i=0; *driver->dependentfiles[i]; i++) {
1406 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1407 !strequal(driver->dependentfiles[i], driver->datafile) &&
1408 !strequal(driver->dependentfiles[i], driver->configfile) &&
1409 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1411 for (j=0; j < i; j++) {
1412 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1417 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1418 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1419 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1421 status = rename_internals(conn, new_name, old_name, True);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1424 new_name, old_name));
1425 *perr = ntstatus_to_werror(status);
1426 unlink_internals(conn, 0, new_name);
1431 unlink_internals(conn, 0, new_name);
1437 close_cnum(conn, user->vuid);
1440 return ver == -1 ? False : True;
1443 /****************************************************************************
1444 ****************************************************************************/
1445 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1448 fstring architecture;
1454 TDB_DATA kbuf, dbuf;
1456 get_short_archi(architecture, driver->environment);
1458 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1459 * \\server is added in the rpc server layer.
1460 * It does make sense to NOT store the server's name in the printer TDB.
1463 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1465 /* .inf files do not always list a file for each of the four standard files.
1466 * Don't prepend a path to a null filename, or client claims:
1467 * "The server on which the printer resides does not have a suitable
1468 * <printer driver name> printer driver installed. Click OK if you
1469 * wish to install the driver on your local machine."
1471 if (strlen(driver->driverpath)) {
1472 fstrcpy(temp_name, driver->driverpath);
1473 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1476 if (strlen(driver->datafile)) {
1477 fstrcpy(temp_name, driver->datafile);
1478 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1481 if (strlen(driver->configfile)) {
1482 fstrcpy(temp_name, driver->configfile);
1483 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1486 if (strlen(driver->helpfile)) {
1487 fstrcpy(temp_name, driver->helpfile);
1488 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1491 if (driver->dependentfiles) {
1492 for (i=0; *driver->dependentfiles[i]; i++) {
1493 fstrcpy(temp_name, driver->dependentfiles[i]);
1494 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1498 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1500 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1507 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1510 driver->environment,
1515 driver->monitorname,
1516 driver->defaultdatatype);
1518 if (driver->dependentfiles) {
1519 for (i=0; *driver->dependentfiles[i]; i++) {
1520 len += tdb_pack(buf+len, buflen-len, "f",
1521 driver->dependentfiles[i]);
1525 if (len != buflen) {
1528 tb = (char *)Realloc(buf, len);
1530 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1541 kbuf.dsize = strlen(key)+1;
1545 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1549 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1555 /****************************************************************************
1556 ****************************************************************************/
1557 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1559 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1562 info3.cversion = driver->version;
1563 fstrcpy(info3.name,driver->name);
1564 fstrcpy(info3.environment,driver->environment);
1565 fstrcpy(info3.driverpath,driver->driverpath);
1566 fstrcpy(info3.datafile,driver->datafile);
1567 fstrcpy(info3.configfile,driver->configfile);
1568 fstrcpy(info3.helpfile,driver->helpfile);
1569 fstrcpy(info3.monitorname,driver->monitorname);
1570 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1571 info3.dependentfiles = driver->dependentfiles;
1573 return add_a_printer_driver_3(&info3);
1577 /****************************************************************************
1578 ****************************************************************************/
1579 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1581 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1585 fstrcpy(info.name, in_prt);
1586 fstrcpy(info.defaultdatatype, "RAW");
1588 fstrcpy(info.driverpath, "");
1589 fstrcpy(info.datafile, "");
1590 fstrcpy(info.configfile, "");
1591 fstrcpy(info.helpfile, "");
1593 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1596 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1597 fstrcpy(info.dependentfiles[0], "");
1599 *info_ptr = memdup(&info, sizeof(info));
1604 /****************************************************************************
1605 ****************************************************************************/
1606 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1608 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1609 TDB_DATA kbuf, dbuf;
1610 fstring architecture;
1615 ZERO_STRUCT(driver);
1617 get_short_archi(architecture, in_arch);
1619 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1621 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1624 kbuf.dsize = strlen(key)+1;
1626 dbuf = tdb_fetch(tdb_drivers, kbuf);
1628 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1630 if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1632 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1641 driver.defaultdatatype);
1644 while (len < dbuf.dsize) {
1647 tddfs = (fstring *)Realloc(driver.dependentfiles,
1648 sizeof(fstring)*(i+2));
1649 if (tddfs == NULL) {
1650 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1653 else driver.dependentfiles = tddfs;
1655 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1656 &driver.dependentfiles[i]);
1659 if (driver.dependentfiles != NULL)
1660 fstrcpy(driver.dependentfiles[i], "");
1662 SAFE_FREE(dbuf.dptr);
1664 if (len != dbuf.dsize) {
1665 SAFE_FREE(driver.dependentfiles);
1667 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1670 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1675 /****************************************************************************
1676 ****************************************************************************/
1677 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1679 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1685 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1686 DEBUG(10,("driver key: [%s]\n", key));
1689 kbuf.dsize = strlen(key)+1;
1690 if (!tdb_exists(tdb_drivers, kbuf)) return False;
1693 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1695 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1696 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1697 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1698 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1699 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1700 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1701 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1703 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1704 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1705 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1707 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1708 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1709 pstrcat(line, info3->configfile);
1711 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1712 pstrcat(line, info3->datafile);
1714 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1715 pstrcat(line, info3->helpfile);
1717 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1718 pstrcat(line, info3->monitorname);
1720 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1723 for (i=0; info3->dependentfiles &&
1724 *info3->dependentfiles[i]; i++) {
1725 if (i) pstrcat(line, ","); /* don't end in a "," */
1726 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1727 pstrcat(line, info3->dependentfiles[i]);
1735 /****************************************************************************
1736 debugging function, dump at level 6 the struct in the logs
1737 ****************************************************************************/
1738 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1741 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1744 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1750 if (driver.info_3 == NULL)
1753 info3=driver.info_3;
1755 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1756 DEBUGADD(106,("name:[%s]\n", info3->name));
1757 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1758 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1759 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1760 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1761 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1762 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1763 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1765 for (i=0; info3->dependentfiles &&
1766 *info3->dependentfiles[i]; i++) {
1767 DEBUGADD(106,("dependentfile:[%s]\n",
1768 info3->dependentfiles[i]));
1775 DEBUGADD(1,("Level not implemented\n"));
1783 /****************************************************************************
1784 ****************************************************************************/
1785 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1789 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1791 if (!nt_devmode) return len;
1793 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1794 nt_devmode->devicename,
1795 nt_devmode->formname,
1797 nt_devmode->specversion,
1798 nt_devmode->driverversion,
1800 nt_devmode->driverextra,
1801 nt_devmode->orientation,
1802 nt_devmode->papersize,
1803 nt_devmode->paperlength,
1804 nt_devmode->paperwidth,
1807 nt_devmode->defaultsource,
1808 nt_devmode->printquality,
1811 nt_devmode->yresolution,
1812 nt_devmode->ttoption,
1813 nt_devmode->collate,
1814 nt_devmode->logpixels,
1817 nt_devmode->bitsperpel,
1818 nt_devmode->pelswidth,
1819 nt_devmode->pelsheight,
1820 nt_devmode->displayflags,
1821 nt_devmode->displayfrequency,
1822 nt_devmode->icmmethod,
1823 nt_devmode->icmintent,
1824 nt_devmode->mediatype,
1825 nt_devmode->dithertype,
1826 nt_devmode->reserved1,
1827 nt_devmode->reserved2,
1828 nt_devmode->panningwidth,
1829 nt_devmode->panningheight,
1830 nt_devmode->private);
1833 if (nt_devmode->private) {
1834 len += tdb_pack(buf+len, buflen-len, "B",
1835 nt_devmode->driverextra,
1836 nt_devmode->private);
1839 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1844 /****************************************************************************
1845 ****************************************************************************/
1846 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1850 while (param != NULL) {
1851 len += tdb_pack(buf+len, buflen-len, "pfdB",
1860 len += tdb_pack(buf+len, buflen-len, "p", param);
1866 /****************************************************************************
1867 delete a printer - this just deletes the printer info file, any open
1868 handles are not affected
1869 ****************************************************************************/
1870 uint32 del_a_printer(char *sharename)
1875 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1878 kbuf.dsize=strlen(key)+1;
1880 tdb_delete(tdb_printers, kbuf);
1884 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1885 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1886 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1887 /****************************************************************************
1888 ****************************************************************************/
1889 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1895 TDB_DATA kbuf, dbuf;
1898 * in addprinter: no servername and the printer is the name
1899 * in setprinter: servername is \\server
1900 * and printer is \\server\\printer
1902 * Samba manages only local printers.
1903 * we currently don't support things like path=\\other_server\printer
1906 if (info->servername[0]!='\0') {
1907 trim_string(info->printername, info->servername, NULL);
1908 trim_string(info->printername, "\\", NULL);
1909 info->servername[0]='\0';
1913 * JFM: one day I'll forget.
1914 * below that's info->portname because that's the SAMBA sharename
1915 * and I made NT 'thinks' it's the portname
1916 * the info->sharename is the thing you can name when you add a printer
1917 * that's the short-name when you create shared printer for 95/98
1918 * So I've made a limitation in SAMBA: you can only have 1 printer model
1919 * behind a SAMBA share.
1927 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1930 info->default_priority,
1947 info->printprocessor,
1951 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1953 len += pack_specifics(info->specific, buf+len, buflen-len);
1955 if (buflen != len) {
1958 tb = (char *)Realloc(buf, len);
1960 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1970 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1973 kbuf.dsize = strlen(key)+1;
1977 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
1980 if (!W_ERROR_IS_OK(ret))
1981 DEBUG(8, ("error updating printer to tdb on disk\n"));
1985 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1986 info->sharename, info->drivername, info->portname, len));
1992 /****************************************************************************
1993 ****************************************************************************/
1994 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1996 NT_PRINTER_PARAM *current;
1998 DEBUG(108,("add_a_specific_param\n"));
2000 (*param)->next=NULL;
2002 if (info_2->specific == NULL)
2004 info_2->specific=*param;
2008 current=info_2->specific;
2009 while (current->next != NULL) {
2010 current=current->next;
2012 current->next=*param;
2018 /****************************************************************************
2019 ****************************************************************************/
2020 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2022 NT_PRINTER_PARAM *current;
2023 NT_PRINTER_PARAM *previous;
2025 current=info_2->specific;
2028 if (current==NULL) return (False);
2030 if ( !strcmp(current->value, param->value) &&
2031 (strlen(current->value)==strlen(param->value)) ) {
2032 DEBUG(109,("deleting first value\n"));
2033 info_2->specific=current->next;
2034 SAFE_FREE(current->data);
2036 DEBUG(109,("deleted first value\n"));
2040 current=previous->next;
2042 while ( current!=NULL ) {
2043 if (!strcmp(current->value, param->value) &&
2044 strlen(current->value)==strlen(param->value) ) {
2045 DEBUG(109,("deleting current value\n"));
2046 previous->next=current->next;
2047 SAFE_FREE(current->data);
2049 DEBUG(109,("deleted current value\n"));
2053 previous=previous->next;
2054 current=current->next;
2059 /****************************************************************************
2060 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2061 ****************************************************************************/
2062 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2064 NT_PRINTER_PARAM *param = *param_ptr;
2069 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2071 SAFE_FREE(param->data);
2072 SAFE_FREE(*param_ptr);
2075 /****************************************************************************
2076 Malloc and return an NT devicemode.
2077 ****************************************************************************/
2079 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2082 * should I init this ones ???
2083 nt_devmode->devicename
2087 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2089 if (nt_devmode == NULL) {
2090 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2094 ZERO_STRUCTP(nt_devmode);
2096 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2097 fstrcpy(nt_devmode->devicename, adevice);
2099 fstrcpy(nt_devmode->formname, "Letter");
2101 nt_devmode->specversion = 0x0401;
2102 nt_devmode->driverversion = 0x0400;
2103 nt_devmode->size = 0x00DC;
2104 nt_devmode->driverextra = 0x0000;
2105 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2106 DEFAULTSOURCE | COPIES | SCALE |
2107 PAPERSIZE | ORIENTATION;
2108 nt_devmode->orientation = 1;
2109 nt_devmode->papersize = PAPER_LETTER;
2110 nt_devmode->paperlength = 0;
2111 nt_devmode->paperwidth = 0;
2112 nt_devmode->scale = 0x64;
2113 nt_devmode->copies = 1;
2114 nt_devmode->defaultsource = BIN_FORMSOURCE;
2115 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2116 nt_devmode->color = COLOR_MONOCHROME;
2117 nt_devmode->duplex = DUP_SIMPLEX;
2118 nt_devmode->yresolution = 0;
2119 nt_devmode->ttoption = TT_SUBDEV;
2120 nt_devmode->collate = COLLATE_FALSE;
2121 nt_devmode->icmmethod = 0;
2122 nt_devmode->icmintent = 0;
2123 nt_devmode->mediatype = 0;
2124 nt_devmode->dithertype = 0;
2126 /* non utilisés par un driver d'imprimante */
2127 nt_devmode->logpixels = 0;
2128 nt_devmode->bitsperpel = 0;
2129 nt_devmode->pelswidth = 0;
2130 nt_devmode->pelsheight = 0;
2131 nt_devmode->displayflags = 0;
2132 nt_devmode->displayfrequency = 0;
2133 nt_devmode->reserved1 = 0;
2134 nt_devmode->reserved2 = 0;
2135 nt_devmode->panningwidth = 0;
2136 nt_devmode->panningheight = 0;
2138 nt_devmode->private = NULL;
2142 /****************************************************************************
2143 Deepcopy an NT devicemode.
2144 ****************************************************************************/
2146 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2148 NT_DEVICEMODE *new_nt_devicemode = NULL;
2150 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2151 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2155 new_nt_devicemode->private = NULL;
2156 if (nt_devicemode->private != NULL) {
2157 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2158 SAFE_FREE(new_nt_devicemode);
2159 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2164 return new_nt_devicemode;
2167 /****************************************************************************
2168 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2169 ****************************************************************************/
2171 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2173 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2175 if(nt_devmode == NULL)
2178 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2180 SAFE_FREE(nt_devmode->private);
2181 SAFE_FREE(*devmode_ptr);
2184 /****************************************************************************
2185 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2186 ****************************************************************************/
2187 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2189 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2190 NT_PRINTER_PARAM *param_ptr;
2195 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2197 free_nt_devicemode(&info->devmode);
2199 for(param_ptr = info->specific; param_ptr; ) {
2200 NT_PRINTER_PARAM *tofree = param_ptr;
2202 param_ptr = param_ptr->next;
2203 free_nt_printer_param(&tofree);
2206 SAFE_FREE(*info_ptr);
2210 /****************************************************************************
2211 ****************************************************************************/
2212 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2216 NT_DEVICEMODE devmode;
2218 ZERO_STRUCT(devmode);
2220 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2222 if (!*nt_devmode) return len;
2224 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2228 &devmode.specversion,
2229 &devmode.driverversion,
2231 &devmode.driverextra,
2232 &devmode.orientation,
2234 &devmode.paperlength,
2235 &devmode.paperwidth,
2238 &devmode.defaultsource,
2239 &devmode.printquality,
2242 &devmode.yresolution,
2248 &devmode.bitsperpel,
2250 &devmode.pelsheight,
2251 &devmode.displayflags,
2252 &devmode.displayfrequency,
2256 &devmode.dithertype,
2259 &devmode.panningwidth,
2260 &devmode.panningheight,
2263 if (devmode.private) {
2264 /* the len in tdb_unpack is an int value and
2265 * devmode.driverextra is only a short
2267 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2268 devmode.driverextra=(uint16)extra_len;
2270 /* check to catch an invalid TDB entry so we don't segfault */
2271 if (devmode.driverextra == 0) {
2272 devmode.private = NULL;
2276 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2278 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2279 if (devmode.private)
2280 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2285 /****************************************************************************
2286 ****************************************************************************/
2287 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2290 NT_PRINTER_PARAM param, *p;
2295 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2298 len += tdb_unpack(buf+len, buflen-len, "fdB",
2304 *list = memdup(¶m, sizeof(param));
2306 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2312 static void map_to_os2_driver(fstring drivername)
2314 static BOOL initialised=False;
2315 static fstring last_from,last_to;
2316 char *mapfile = lp_os2_driver_map();
2317 char **lines = NULL;
2321 if (!strlen(drivername))
2328 *last_from = *last_to = 0;
2332 if (strequal(drivername,last_from)) {
2333 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2334 fstrcpy(drivername,last_to);
2338 lines = file_lines_load(mapfile, &numlines);
2339 if (numlines == 0) {
2340 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2344 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2346 for( i = 0; i < numlines; i++) {
2347 char *nt_name = lines[i];
2348 char *os2_name = strchr(nt_name,'=');
2355 while (isspace(*nt_name))
2358 if (!*nt_name || strchr("#;",*nt_name))
2362 int l = strlen(nt_name);
2363 while (l && isspace(nt_name[l-1])) {
2369 while (isspace(*os2_name))
2373 int l = strlen(os2_name);
2374 while (l && isspace(os2_name[l-1])) {
2380 if (strequal(nt_name,drivername)) {
2381 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2382 fstrcpy(last_from,drivername);
2383 fstrcpy(last_to,os2_name);
2384 fstrcpy(drivername,os2_name);
2385 file_lines_free(lines);
2390 file_lines_free(lines);
2393 /****************************************************************************
2394 get a default printer info 2 struct
2395 ****************************************************************************/
2396 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2399 NT_PRINTER_INFO_LEVEL_2 info;
2403 snum = lp_servicenumber(sharename);
2405 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2406 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2407 get_called_name(), sharename);
2408 fstrcpy(info.sharename, sharename);
2409 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2410 fstrcpy(info.drivername, lp_printerdriver(snum));
2412 /* by setting the driver name to an empty string, a local NT admin
2413 can now run the **local** APW to install a local printer driver
2414 for a Samba shared printer in 2.2. Without this, drivers **must** be
2415 installed on the Samba server for NT clients --jerry */
2416 #if 0 /* JERRY --do not uncomment-- */
2417 if (!*info.drivername)
2418 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2422 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2424 pstrcpy(info.comment, "");
2425 fstrcpy(info.printprocessor, "winprint");
2426 fstrcpy(info.datatype, "RAW");
2428 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2429 | PRINTER_ATTRIBUTE_LOCAL \
2430 | PRINTER_ATTRIBUTE_RAW_ONLY \
2431 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2433 info.starttime = 0; /* Minutes since 12:00am GMT */
2434 info.untiltime = 0; /* Minutes since 12:00am GMT */
2436 info.default_priority = 1;
2437 info.setuptime = (uint32)time(NULL) - 86400; /* minus 1 day */
2440 * I changed this as I think it is better to have a generic
2441 * DEVMODE than to crash Win2k explorer.exe --jerry
2442 * See the HP Deskjet 990c Win2k drivers for an example.
2445 #if 0 /* JRA - NO NOT CHANGE ! */
2446 info.devmode = NULL;
2449 * We should not return a default devicemode, as this causes
2450 * Win2K to not send the correct one on PCL drivers. It needs to
2451 * see a null devicemode so it can then overwrite the devicemode
2452 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2454 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2458 /* This will get the current RPC talloc context, but we should be
2459 passing this as a parameter... fixme... JRA ! */
2461 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2464 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2466 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2475 free_nt_devicemode(&info.devmode);
2476 return WERR_ACCESS_DENIED;
2479 /****************************************************************************
2480 ****************************************************************************/
2481 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2484 NT_PRINTER_INFO_LEVEL_2 info;
2486 TDB_DATA kbuf, dbuf;
2487 fstring printername;
2491 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2494 kbuf.dsize = strlen(key)+1;
2496 dbuf = tdb_fetch(tdb_printers, kbuf);
2498 return get_a_printer_2_default(info_ptr, sharename);
2500 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2503 &info.default_priority,
2520 info.printprocessor,
2524 /* Samba has to have shared raw drivers. */
2525 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2527 /* Restore the stripped strings. */
2528 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2529 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2531 fstrcpy(info.printername, printername);
2533 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2536 * Some client drivers freak out if there is a NULL devmode
2537 * (probably the driver is not checking before accessing
2538 * the devmode pointer) --jerry
2542 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2544 info.devmode = construct_nt_devicemode(printername);
2547 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2549 /* This will get the current RPC talloc context, but we should be
2550 passing this as a parameter... fixme... JRA ! */
2552 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2554 /* Fix for OS/2 drivers. */
2556 if (get_remote_arch() == RA_OS2)
2557 map_to_os2_driver(info.drivername);
2559 SAFE_FREE(dbuf.dptr);
2560 *info_ptr=memdup(&info, sizeof(info));
2562 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2563 sharename, info.printername, info.drivername));
2568 /****************************************************************************
2569 debugging function, dump at level 6 the struct in the logs
2570 ****************************************************************************/
2571 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2574 NT_PRINTER_INFO_LEVEL_2 *info2;
2576 DEBUG(106,("Dumping printer at level [%d]\n", level));
2582 if (printer.info_2 == NULL)
2586 info2=printer.info_2;
2588 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2589 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2590 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2591 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2592 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2593 DEBUGADD(106,("status:[%d]\n", info2->status));
2594 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2595 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2596 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2597 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2598 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2600 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2601 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2602 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2603 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2604 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2605 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2606 DEBUGADD(106,("location:[%s]\n", info2->location));
2607 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2608 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2609 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2610 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2616 DEBUGADD(1,("Level not implemented\n"));
2624 /****************************************************************************
2625 Get the parameters we can substitute in an NT print job.
2626 ****************************************************************************/
2628 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2630 NT_PRINTER_INFO_LEVEL *printer = NULL;
2632 **printername = **sharename = **portname = '\0';
2634 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2637 fstrcpy(*printername, printer->info_2->printername);
2638 fstrcpy(*sharename, printer->info_2->sharename);
2639 fstrcpy(*portname, printer->info_2->portname);
2641 free_a_printer(&printer, 2);
2644 /****************************************************************************
2645 Update the changeid time.
2646 This is SO NASTY as some drivers need this to change, others need it
2647 static. This value will change every second, and I must hope that this
2648 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2650 ****************************************************************************/
2652 static uint32 rev_changeid(void)
2654 static time_t start_time;
2655 if (start_time == 0)
2656 start_time = time(NULL);
2657 return (((time(NULL) - start_time)+1)*1000);
2661 * The function below are the high level ones.
2662 * only those ones must be called from the spoolss code.
2666 /****************************************************************************
2667 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2668 ****************************************************************************/
2670 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2674 dump_a_printer(printer, level);
2681 * Update the changestamp. Emperical tests show that the
2682 * ChangeID is always updated,but c_setprinter is only
2683 * incremented on a SetPrinter() call.
2686 /* ChangeID **must** be increasing over the lifetime
2687 of client's spoolss service in order for the
2688 client's cache to show updates */
2690 printer.info_2->changeid = rev_changeid();
2693 * Because one day someone will ask:
2694 * NT->NT An admin connection to a remote
2695 * printer show changes imeediately in
2696 * the properities dialog
2698 * A non-admin connection will only show the
2699 * changes after viewing the properites page
2700 * 2 times. Seems to be related to a
2701 * race condition in the client between the spooler
2702 * updating the local cache and the Explorer.exe GUI
2703 * actually displaying the properties.
2705 * This is fixed in Win2k. admin/non-admin
2706 * connections both display changes immediately.
2711 result=update_a_printer_2(printer.info_2);
2715 result=WERR_UNKNOWN_LEVEL;
2722 /****************************************************************************
2723 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2724 We split this out from mod_a_printer as it updates the id's and timestamps.
2725 ****************************************************************************/
2727 WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2731 dump_a_printer(printer, level);
2738 * Update the changestamp. See comments in mod_a_printer()
2742 printer.info_2->changeid = rev_changeid();
2743 printer.info_2->c_setprinter++;
2745 result=update_a_printer_2(printer.info_2);
2749 result=WERR_UNKNOWN_LEVEL;
2756 /****************************************************************************
2757 Initialize printer devmode & data with previously saved driver init values.
2758 ****************************************************************************/
2759 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2763 TDB_DATA kbuf, dbuf;
2764 NT_PRINTER_PARAM *current;
2765 NT_PRINTER_INFO_LEVEL_2 info;
2769 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2772 kbuf.dsize = strlen(key)+1;
2774 dbuf = tdb_fetch(tdb_drivers, kbuf);
2779 * Get the saved DEVMODE..
2781 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2784 * The saved DEVMODE contains the devicename from the printer used during
2785 * the initialization save. Change it to reflect the new printer.
2787 ZERO_STRUCT(info.devmode->devicename);
2788 fstrcpy(info.devmode->devicename, info_ptr->printername);
2791 * Bind the saved DEVMODE to the new the printer.
2793 free_nt_devicemode(&info_ptr->devmode);
2794 info_ptr->devmode = info.devmode;
2796 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2797 info_ptr->printername, info_ptr->drivername));
2800 * There should not be any printer data 'specifics' already set during the
2801 * add printer operation, if there are delete them.
2803 while ( (current=info_ptr->specific) != NULL ) {
2804 info_ptr->specific=current->next;
2805 SAFE_FREE(current->data);
2810 * Add the printer data 'specifics' to the new printer
2812 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2814 SAFE_FREE(dbuf.dptr);
2819 /****************************************************************************
2820 Initialize printer devmode & data with previously saved driver init values.
2821 When a printer is created using AddPrinter, the drivername bound to the
2822 printer is used to lookup previously saved driver initialization info, which
2823 is bound to the new printer.
2824 ****************************************************************************/
2826 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2834 result=set_driver_init_2(printer->info_2);
2845 /****************************************************************************
2846 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2847 in the tdb. Note: this is different from the driver entry and the printer
2848 entry. There should be a single driver init entry for each driver regardless
2849 of whether it was installed from NT or 2K. Technically, they should be
2850 different, but they work out to the same struct.
2851 ****************************************************************************/
2852 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2856 int buflen, len, ret;
2857 TDB_DATA kbuf, dbuf;
2864 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2866 len += pack_specifics(info->specific, buf+len, buflen-len);
2868 if (buflen != len) {
2871 tb = (char *)Realloc(buf, len);
2873 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2882 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2885 kbuf.dsize = strlen(key)+1;
2889 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2893 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2897 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2898 info->sharename, info->drivername));
2903 /****************************************************************************
2904 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2905 ****************************************************************************/
2907 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2911 dump_a_printer(printer, level);
2917 result=update_driver_init_2(printer.info_2);
2928 /****************************************************************************
2929 Convert the printer data value, a REG_BINARY array, into an initialization
2930 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2931 got to keep the endians happy :).
2932 ****************************************************************************/
2934 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2936 BOOL result = False;
2940 ZERO_STRUCT(devmode);
2942 prs_init(&ps, 0, ctx, UNMARSHALL);
2943 ps.data_p = (char *)param->data;
2944 ps.buffer_size = param->data_len;
2946 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2947 result = convert_devicemode("", &devmode, &nt_devmode);
2949 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2954 /****************************************************************************
2955 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2957 1. Use the driver's config DLL to this UNC printername and:
2958 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2959 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2960 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2962 The last step triggers saving the "driver initialization" information for
2963 this printer into the tdb. Later, new printers that use this driver will
2964 have this initialization information bound to them. This simulates the
2965 driver initialization, as if it had run on the Samba server (as it would
2968 The Win32 client side code requirement sucks! But until we can run arbitrary
2969 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2971 It would have been easier to use SetPrinter because all the UNMARSHALLING of
2972 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2973 about it and you will realize why. JRR 010720
2974 ****************************************************************************/
2976 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2978 WERROR status = WERR_OK;
2979 TALLOC_CTX *ctx = NULL;
2980 NT_DEVICEMODE *nt_devmode = NULL;
2981 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2984 * Set devmode on printer info, so entire printer initialization can be
2987 if ((ctx = talloc_init()) == NULL)
2990 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2991 status = WERR_NOMEM;
2995 ZERO_STRUCTP(nt_devmode);
2998 * The DEVMODE is held in the 'data' component of the param in raw binary.
2999 * Convert it to to a devmode structure
3001 if (!convert_driver_init(param, ctx, nt_devmode)) {
3002 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3003 status = WERR_INVALID_PARAM;
3008 * Pack up and add (or update) the DEVMODE and any current printer data to
3009 * a 'driver init' element in the tdb
3012 printer->info_2->devmode = nt_devmode;
3013 if (update_driver_init(*printer, 2)!=0) {
3014 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3015 status = WERR_NOMEM;
3020 * If driver initialization info was successfully saved, set the current
3021 * printer to match it. This allows initialization of the current printer
3022 * as well as the driver.
3024 status = mod_a_printer(*printer, 2);
3025 if (!W_ERROR_IS_OK(status)) {
3026 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3027 printer->info_2->printername));
3031 talloc_destroy(ctx);
3033 SAFE_FREE(nt_devmode->private);
3034 SAFE_FREE(nt_devmode);
3035 printer->info_2->devmode = tmp_devmode;
3040 /****************************************************************************
3041 Update the driver init info (DEVMODE and specifics) for a printer
3042 ****************************************************************************/
3044 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3046 WERROR status = WERR_OK;
3052 status=save_driver_init_2(printer, param);
3056 status=WERR_UNKNOWN_LEVEL;
3063 /****************************************************************************
3064 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3065 ****************************************************************************/
3067 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3070 NT_PRINTER_INFO_LEVEL *printer = NULL;
3074 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3080 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3081 DEBUG(0,("get_a_printer: malloc fail.\n"));
3084 ZERO_STRUCTP(printer);
3085 result=get_a_printer_2(&printer->info_2, sharename);
3086 if (W_ERROR_IS_OK(result)) {
3087 dump_a_printer(*printer, level);
3088 *pp_printer = printer;
3095 result=WERR_UNKNOWN_LEVEL;
3099 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, werror_str(result)));
3104 /****************************************************************************
3105 Deletes a NT_PRINTER_INFO_LEVEL struct.
3106 ****************************************************************************/
3108 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3111 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3113 DEBUG(104,("freeing a printer at level [%d]\n", level));
3115 if (printer == NULL)
3122 if (printer->info_2 != NULL)
3124 free_nt_printer_info_level_2(&printer->info_2);
3138 SAFE_FREE(*pp_printer);
3142 /****************************************************************************
3143 ****************************************************************************/
3144 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3147 DEBUG(104,("adding a printer at level [%d]\n", level));
3148 dump_a_printer_driver(driver, level);
3154 result=add_a_printer_driver_3(driver.info_3);
3160 result=add_a_printer_driver_6(driver.info_6);
3170 /****************************************************************************
3171 ****************************************************************************/
3172 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3173 fstring printername, fstring architecture, uint32 version)
3181 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3189 if (W_ERROR_IS_OK(result))
3190 dump_a_printer_driver(*driver, level);
3194 /****************************************************************************
3195 ****************************************************************************/
3196 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3204 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3205 if (driver.info_3 != NULL)
3207 info3=driver.info_3;
3208 SAFE_FREE(info3->dependentfiles);
3209 ZERO_STRUCTP(info3);
3221 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3222 if (driver.info_6 != NULL)
3224 info6=driver.info_6;
3225 SAFE_FREE(info6->dependentfiles);
3226 SAFE_FREE(info6->previousnames);
3227 ZERO_STRUCTP(info6);
3245 /****************************************************************************
3246 Determine whether or not a particular driver is currently assigned
3248 ****************************************************************************/
3249 BOOL printer_driver_in_use (char *arch, char *driver)
3251 TDB_DATA kbuf, newkey, dbuf;
3252 NT_PRINTER_INFO_LEVEL_2 info;
3256 if (!nt_printing_init())
3259 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3261 /* loop through the printers.tdb and check for the drivername */
3262 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3263 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3266 dbuf = tdb_fetch(tdb_printers, kbuf);
3270 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3273 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3276 &info.default_priority,
3293 info.printprocessor,
3297 SAFE_FREE(dbuf.dptr);
3300 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3305 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3306 info.printername, info.drivername));
3308 if (strcmp(info.drivername, driver) == 0)
3310 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3311 info.printername, driver));
3315 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3319 /* report that the driver is in use by default */
3323 /****************************************************************************
3324 Remove a printer driver from the TDB. This assumes that the the driver was
3325 previously looked up.
3326 ***************************************************************************/
3327 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3334 get_short_archi(arch, i->environment);
3335 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3336 arch, i->cversion, i->name);
3337 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3340 kbuf.dsize=strlen(key)+1;
3342 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3343 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3344 return WERR_ACCESS_DENIED;
3347 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3352 /****************************************************************************
3353 ****************************************************************************/
3354 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3355 fstring value, uint8 **data, uint32 *type, uint32 *len)
3357 /* right now that's enough ! */
3358 NT_PRINTER_PARAM *param;
3361 param=printer.info_2->specific;
3363 while (param != NULL && i < param_index) {
3371 /* exited because it exist */
3373 StrnCpy(value, param->value, sizeof(fstring)-1);
3374 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3377 ZERO_STRUCTP(*data);
3378 memcpy(*data, param->data, param->data_len);
3379 *len=param->data_len;
3383 /****************************************************************************
3384 ****************************************************************************/
3385 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3386 fstring value, uint8 **data, uint32 *type, uint32 *len)
3388 /* right now that's enough ! */
3389 NT_PRINTER_PARAM *param;
3391 DEBUG(10, ("get_specific_param\n"));
3393 param=printer.info_2->specific;
3395 while (param != NULL)
3397 #if 1 /* JRA - I think this should be case insensitive.... */
3398 if ( strequal(value, param->value)
3400 if ( !strcmp(value, param->value)
3402 && strlen(value)==strlen(param->value))
3410 DEBUGADD(10, ("get_specific_param: found one param\n"));
3411 /* exited because it exist */
3414 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3417 memcpy(*data, param->data, param->data_len);
3418 *len=param->data_len;
3420 DEBUGADD(10, ("get_specific_param: exit true\n"));
3423 DEBUGADD(10, ("get_specific_param: exit false\n"));
3427 /****************************************************************************
3428 Store a security desc for a printer.
3429 ****************************************************************************/
3431 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3433 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3434 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3436 TALLOC_CTX *mem_ctx = NULL;
3440 mem_ctx = talloc_init();
3441 if (mem_ctx == NULL)
3444 /* The old owner and group sids of the security descriptor are not
3445 present when new ACEs are added or removed by changing printer
3446 permissions through NT. If they are NULL in the new security
3447 descriptor then copy them over from the old one. */
3449 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3450 DOM_SID *owner_sid, *group_sid;
3451 SEC_ACL *dacl, *sacl;
3452 SEC_DESC *psd = NULL;
3455 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3457 /* Pick out correct owner and group sids */
3459 owner_sid = secdesc_ctr->sec->owner_sid ?
3460 secdesc_ctr->sec->owner_sid :
3461 old_secdesc_ctr->sec->owner_sid;
3463 group_sid = secdesc_ctr->sec->grp_sid ?
3464 secdesc_ctr->sec->grp_sid :
3465 old_secdesc_ctr->sec->grp_sid;
3467 dacl = secdesc_ctr->sec->dacl ?
3468 secdesc_ctr->sec->dacl :
3469 old_secdesc_ctr->sec->dacl;
3471 sacl = secdesc_ctr->sec->sacl ?
3472 secdesc_ctr->sec->sacl :
3473 old_secdesc_ctr->sec->sacl;
3475 /* Make a deep copy of the security descriptor */
3477 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3478 owner_sid, group_sid,
3483 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3486 if (!new_secdesc_ctr) {
3487 new_secdesc_ctr = secdesc_ctr;
3490 /* Store the security descriptor in a tdb */
3492 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3493 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3495 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3497 status = WERR_BADFUNC;
3501 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3503 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3506 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3507 status = WERR_BADFUNC;
3510 /* Free malloc'ed memory */
3516 talloc_destroy(mem_ctx);
3520 /****************************************************************************
3521 Construct a default security descriptor buffer for a printer.
3522 ****************************************************************************/
3524 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3528 SEC_ACL *psa = NULL;
3529 SEC_DESC_BUF *sdb = NULL;
3530 SEC_DESC *psd = NULL;
3533 enum SID_NAME_USE name_type;
3535 /* Create an ACE where Everyone is allowed to print */
3537 init_sec_access(&sa, PRINTER_ACE_PRINT);
3538 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3539 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3541 /* Make the security descriptor owned by the Administrators group
3542 on the PDC of the domain. */
3544 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3545 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3549 /* Backup plan - make printer owned by admins or root.
3550 This should emulate a lanman printer as security
3551 settings can't be changed. */
3553 sid_peek_rid(&owner_sid, &owner_rid);
3555 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3556 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3557 owner_rid != DOMAIN_USER_RID_ADMIN &&
3558 !lookup_name("root", &owner_sid, &name_type)) {
3559 sid_copy(&owner_sid, &global_sid_World);
3563 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3564 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3565 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3566 SEC_ACE_FLAG_INHERIT_ONLY);
3568 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3569 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3570 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3572 /* The ACL revision number in rpc_secdesc.h differs from the one
3573 created by NT when setting ACE entries in printer
3574 descriptors. NT4 complains about the property being edited by a
3577 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3578 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3580 NULL, psa, &sd_size);
3584 DEBUG(0,("construct_default_printer_sdb: Failed to make SEC_DESC.\n"));
3588 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3590 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3591 (unsigned int)sd_size));
3596 /****************************************************************************
3597 Get a security desc for a printer.
3598 ****************************************************************************/
3600 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3606 if ((temp = strchr(printername + 2, '\\'))) {
3607 printername = temp + 1;
3610 /* Fetch security descriptor from tdb */
3612 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3614 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3615 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3617 DEBUG(4,("using default secdesc for %s\n", printername));
3619 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3623 /* Save default security descriptor for later */
3625 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
3626 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
3628 if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
3629 tdb_prs_store(tdb_printers, key, &ps);
3636 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3637 this security descriptor has been created when winbindd was
3638 down. Take ownership of security descriptor. */
3640 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3642 enum SID_NAME_USE name_type;
3644 /* Change sd owner to workgroup administrator */
3646 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3648 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3649 SEC_DESC *psd = NULL;
3654 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3656 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3658 (*secdesc_ctr)->sec->grp_sid,
3659 (*secdesc_ctr)->sec->sacl,
3660 (*secdesc_ctr)->sec->dacl,
3663 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3665 /* Swap with other one */
3667 *secdesc_ctr = new_secdesc_ctr;
3671 nt_printing_setsec(printername, *secdesc_ctr);
3675 if (DEBUGLEVEL >= 10) {
3676 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3679 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3680 printername, the_acl->num_aces));
3682 for (i = 0; i < the_acl->num_aces; i++) {
3685 sid_to_string(sid_str, &the_acl->ace[i].trustee);
3687 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3688 the_acl->ace[i].type, the_acl->ace[i].flags,
3689 the_acl->ace[i].info.mask));
3699 1: level not implemented
3700 2: file doesn't exist
3701 3: can't allocate memory
3702 4: can't free memory
3703 5: non existant struct
3707 A printer and a printer driver are 2 different things.
3708 NT manages them separatelly, Samba does the same.
3709 Why ? Simply because it's easier and it makes sense !
3711 Now explanation: You have 3 printers behind your samba server,
3712 2 of them are the same make and model (laser A and B). But laser B
3713 has an 3000 sheet feeder and laser A doesn't such an option.
3714 Your third printer is an old dot-matrix model for the accounting :-).
3716 If the /usr/local/samba/lib directory (default dir), you will have
3717 5 files to describe all of this.
3719 3 files for the printers (1 by printer):
3722 NTprinter_accounting
3723 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3724 NTdriver_printer model X
3725 NTdriver_printer model Y
3727 jfm: I should use this comment for the text file to explain
3728 same thing for the forms BTW.
3729 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3733 /* Convert generic access rights to printer object specific access rights.
3734 It turns out that NT4 security descriptors use generic access rights and
3735 NT5 the object specific ones. */
3737 void map_printer_permissions(SEC_DESC *sd)
3741 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3742 se_map_generic(&sd->dacl->ace[i].info.mask,
3743 &printer_generic_mapping);
3747 /****************************************************************************
3748 Check a user has permissions to perform the given operation. We use the
3749 permission constants defined in include/rpc_spoolss.h to check the various
3750 actions we perform when checking printer access.
3752 PRINTER_ACCESS_ADMINISTER:
3753 print_queue_pause, print_queue_resume, update_printer_sec,
3754 update_printer, spoolss_addprinterex_level_2,
3755 _spoolss_setprinterdata
3760 JOB_ACCESS_ADMINISTER:
3761 print_job_delete, print_job_pause, print_job_resume,
3764 ****************************************************************************/
3765 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3767 SEC_DESC_BUF *secdesc = NULL;
3768 uint32 access_granted;
3772 TALLOC_CTX *mem_ctx = NULL;
3773 extern struct current_user current_user;
3775 /* If user is NULL then use the current_user structure */
3778 user = ¤t_user;
3780 /* Always allow root or printer admins to do anything */
3782 if (user->uid == 0 ||
3783 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3787 /* Get printer name */
3789 pname = PRINTERNAME(snum);
3791 if (!pname || !*pname) {
3796 /* Get printer security descriptor */
3798 if(!(mem_ctx = talloc_init())) {
3803 nt_printing_getsec(mem_ctx, pname, &secdesc);
3805 if (access_type == JOB_ACCESS_ADMINISTER) {
3806 SEC_DESC_BUF *parent_secdesc = secdesc;
3808 /* Create a child security descriptor to check permissions
3809 against. This is because print jobs are child objects
3810 objects of a printer. */
3812 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3814 /* Now this is the bit that really confuses me. The access
3815 type needs to be changed from JOB_ACCESS_ADMINISTER to
3816 PRINTER_ACCESS_ADMINISTER for this to work. Something
3817 to do with the child (job) object becoming like a
3820 access_type = PRINTER_ACCESS_ADMINISTER;
3825 map_printer_permissions(secdesc->sec);
3827 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
3828 &access_granted, &status);
3830 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3832 talloc_destroy(mem_ctx);
3840 /****************************************************************************
3841 Check the time parameters allow a print operation.
3842 *****************************************************************************/
3844 BOOL print_time_access_check(int snum)
3846 NT_PRINTER_INFO_LEVEL *printer = NULL;
3848 time_t now = time(NULL);
3852 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3855 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3859 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3861 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3864 free_a_printer(&printer, 2);
3872 /****************************************************************************
3873 Attempt to write a default device.
3874 *****************************************************************************/
3876 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3878 NT_PRINTER_INFO_LEVEL *printer = NULL;
3882 * Don't bother if no default devicemode was sent.
3885 if (printer_default->devmode_cont.devmode == NULL)
3888 result = get_a_printer(&printer, 2, lp_servicename(snum));
3889 if (!W_ERROR_IS_OK(result)) return result;
3892 * Just ignore it if we already have a devmode.
3895 if (printer->info_2->devmode != NULL)
3899 * We don't have a devicemode and we're trying to write
3900 * one. Check we have the access needed.
3902 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3904 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3905 PRINTER_ACCESS_ADMINISTER) {
3906 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3907 result = WERR_ACCESS_DENIED;
3911 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3912 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3913 lp_servicename(snum) ));
3914 result = WERR_ACCESS_DENIED;
3915 /*result = NT_STATUS_NO_PROBLEMO;*/
3919 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3922 * Convert the on the wire devicemode format to the internal one.
3925 if (!convert_devicemode(printer->info_2->printername,
3926 printer_default->devmode_cont.devmode,
3927 &printer->info_2->devmode)) {
3928 result = WERR_NOMEM;
3933 * Finally write back to the tdb.
3936 result = add_a_printer(*printer, 2);
3940 free_a_printer(&printer, 2);