2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern DOM_SID global_sid_World;
26 static TDB_CONTEXT *tdb_forms; /* used for forms files */
27 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
28 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
36 #define NTDRIVERS_DATABASE_VERSION_1 1
37 #define NTDRIVERS_DATABASE_VERSION_2 2
38 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
42 /* Map generic permissions to printer object specific permissions */
44 struct generic_mapping printer_generic_mapping = {
51 /* We need one default form to support our default printer. Msoft adds the
52 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
53 array index). Letter is always first, so (for the current code) additions
54 always put things in the correct order. */
55 static nt_forms_struct default_forms[] = {
56 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
57 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
58 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
59 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
60 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
61 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
62 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
63 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
64 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
65 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
66 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
67 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
68 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
69 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
70 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
71 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
72 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
73 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
74 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
75 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
76 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
77 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
78 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
79 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
80 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
81 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
82 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
83 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
84 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
85 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
86 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
87 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
88 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
89 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
90 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
91 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
92 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
93 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
94 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
95 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
96 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
97 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
98 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
99 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
100 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
101 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
102 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
103 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
104 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
105 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
106 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
107 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
108 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
109 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
110 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
111 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
112 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
113 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
114 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
115 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
116 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
117 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
118 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
119 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
120 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
121 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
122 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
123 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
124 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
125 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
126 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
127 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
128 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
129 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
130 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
131 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
132 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
133 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
134 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
135 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
136 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
137 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
138 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
139 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
140 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
141 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
142 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
143 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
144 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
145 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
146 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
147 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
148 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
149 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
150 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
151 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
152 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
153 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
154 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
155 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
156 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
157 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
158 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
159 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
160 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
161 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
162 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
163 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
164 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
165 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
166 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
167 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
168 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
169 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
170 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
171 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
172 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
173 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
176 static BOOL upgrade_to_version_3(void)
178 TDB_DATA kbuf, newkey, dbuf;
180 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
182 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
183 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
185 dbuf = tdb_fetch(tdb_drivers, kbuf);
187 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
188 DEBUG(0,("upgrade_to_version_3:moving form\n"));
189 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
190 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
193 if (tdb_delete(tdb_drivers, kbuf) != 0) {
194 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
199 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
200 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
201 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
202 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
205 if (tdb_delete(tdb_drivers, kbuf) != 0) {
206 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
211 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
212 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
213 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
214 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
217 if (tdb_delete(tdb_drivers, kbuf) != 0) {
218 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
223 SAFE_FREE(dbuf.dptr);
229 /****************************************************************************
230 Open the NT printing tdb.
231 ****************************************************************************/
233 BOOL nt_printing_init(void)
235 static pid_t local_pid;
236 char *vstring = "INFO/version";
238 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
241 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
243 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
244 lock_path("ntdrivers.tdb"), strerror(errno) ));
248 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
250 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
251 lock_path("ntprinters.tdb"), strerror(errno) ));
255 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
257 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
258 lock_path("ntforms.tdb"), strerror(errno) ));
262 local_pid = sys_getpid();
264 /* handle a Samba upgrade */
265 tdb_lock_bystring(tdb_drivers, vstring);
269 /* Cope with byte-reversed older versions of the db. */
270 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
271 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
272 /* Written on a bigendian machine with old fetch_int code. Save as le. */
273 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
274 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
275 vers_id = NTDRIVERS_DATABASE_VERSION;
278 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
280 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
281 if (!upgrade_to_version_3())
284 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
286 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
289 tdb_unlock_bystring(tdb_drivers, vstring);
294 /****************************************************************************
295 get builtin form struct list
296 ****************************************************************************/
297 int get_builtin_ntforms(nt_forms_struct **list)
299 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
300 return sizeof(default_forms) / sizeof(default_forms[0]);
303 /****************************************************************************
304 get a builtin form struct
305 ****************************************************************************/
307 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
311 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
312 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
313 count = sizeof(default_forms) / sizeof(default_forms[0]);
314 for (i=0;i<count;i++) {
315 if (strequal(form_name,default_forms[i].name)) {
316 DEBUGADD(6,("Found builtin form %s \n", form_name));
317 memcpy(form,&default_forms[i],sizeof(*form));
325 /****************************************************************************
326 get a form struct list
327 ****************************************************************************/
328 int get_ntforms(nt_forms_struct **list)
330 TDB_DATA kbuf, newkey, dbuf;
332 nt_forms_struct form;
337 for (kbuf = tdb_firstkey(tdb_forms);
339 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
340 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
342 dbuf = tdb_fetch(tdb_forms, kbuf);
343 if (!dbuf.dptr) continue;
345 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
346 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
347 &i, &form.flag, &form.width, &form.length, &form.left,
348 &form.top, &form.right, &form.bottom);
349 SAFE_FREE(dbuf.dptr);
350 if (ret != dbuf.dsize) continue;
352 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
354 DEBUG(0,("get_ntforms: Realloc fail.\n"));
366 /****************************************************************************
367 write a form struct list
368 ****************************************************************************/
369 int write_ntforms(nt_forms_struct **list, int number)
376 for (i=0;i<number;i++) {
377 /* save index, so list is rebuilt in correct order */
378 len = tdb_pack(buf, sizeof(buf), "dddddddd",
379 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
380 (*list)[i].left, (*list)[i].top, (*list)[i].right,
382 if (len > sizeof(buf)) break;
383 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
384 kbuf.dsize = strlen(key)+1;
388 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
394 /****************************************************************************
395 add a form struct at the end of the list
396 ****************************************************************************/
397 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
405 * NT tries to add forms even when
406 * they are already in the base
407 * only update the values if already present
412 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
413 for (n=0; n<*count; n++) {
414 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
415 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
422 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
423 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
427 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
431 (*list)[n].flag=form->flags;
432 (*list)[n].width=form->size_x;
433 (*list)[n].length=form->size_y;
434 (*list)[n].left=form->left;
435 (*list)[n].top=form->top;
436 (*list)[n].right=form->right;
437 (*list)[n].bottom=form->bottom;
442 /****************************************************************************
443 delete a named form struct
444 ****************************************************************************/
445 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
454 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
456 for (n=0; n<*count; n++) {
457 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
458 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
464 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
465 *ret = WERR_INVALID_PARAM;
469 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
470 kbuf.dsize = strlen(key)+1;
472 if (tdb_delete(tdb_forms, kbuf) != 0) {
480 /****************************************************************************
482 ****************************************************************************/
483 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
487 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
489 DEBUG(106, ("[%s]\n", form_name));
490 for (n=0; n<count; n++)
492 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
493 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
497 if (n==count) return;
499 (*list)[n].flag=form->flags;
500 (*list)[n].width=form->size_x;
501 (*list)[n].length=form->size_y;
502 (*list)[n].left=form->left;
503 (*list)[n].top=form->top;
504 (*list)[n].right=form->right;
505 (*list)[n].bottom=form->bottom;
508 /****************************************************************************
509 get the nt drivers list
511 traverse the database and look-up the matching names
512 ****************************************************************************/
513 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
519 TDB_DATA kbuf, newkey;
521 get_short_archi(short_archi, architecture);
522 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
524 for (kbuf = tdb_firstkey(tdb_drivers);
526 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
527 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
529 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
530 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
535 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
542 /****************************************************************************
543 function to do the mapping between the long architecture name and
545 ****************************************************************************/
546 BOOL get_short_archi(char *short_archi, char *long_archi)
553 struct table archi_table[]=
555 {"Windows 4.0", "WIN40" },
556 {"Windows NT x86", "W32X86" },
557 {"Windows NT R4000", "W32MIPS" },
558 {"Windows NT Alpha_AXP", "W32ALPHA" },
559 {"Windows NT PowerPC", "W32PPC" },
565 DEBUG(107,("Getting architecture dependant directory\n"));
568 } while ( (archi_table[i].long_archi!=NULL ) &&
569 StrCaseCmp(long_archi, archi_table[i].long_archi) );
571 if (archi_table[i].long_archi==NULL) {
572 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
576 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
578 DEBUGADD(108,("index: [%d]\n", i));
579 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
580 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
585 /****************************************************************************
586 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
587 There are two case to be covered here: PE (Portable Executable) and NE (New
588 Executable) files. Both files support the same INFO structure, but PE files
589 store the signature in unicode, and NE files store it as !unicode.
590 returns -1 on error, 1 on version info found, and 0 on no version info found.
591 ****************************************************************************/
593 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
599 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
600 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
601 fname, PE_HEADER_SIZE));
605 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
606 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
607 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
609 goto no_version_info;
612 /* Is this really a DOS header? */
613 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
614 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
615 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
616 goto no_version_info;
619 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
620 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
621 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
623 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
624 goto no_version_info;
627 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
628 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
630 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
631 goto no_version_info;
634 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
635 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
637 int section_table_bytes;
639 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
640 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
641 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
642 /* At this point, we assume the file is in error. It still could be somthing
643 * else besides a PE file, but it unlikely at this point.
648 /* get the section table */
649 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
650 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
652 if ((buf=malloc(section_table_bytes)) == NULL) {
653 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
654 fname, section_table_bytes));
658 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
659 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
664 /* Iterate the section table looking for the resource section ".rsrc" */
665 for (i = 0; i < num_sections; i++) {
666 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
668 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
669 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
670 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
673 if ((buf=malloc(section_bytes)) == NULL) {
674 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
675 fname, section_bytes));
679 /* Seek to the start of the .rsrc section info */
680 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
681 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
686 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
687 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
692 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
693 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
694 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
695 /* Align to next long address */
696 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
698 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
699 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
700 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
702 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
703 fname, *major, *minor,
704 (*major>>16)&0xffff, *major&0xffff,
705 (*minor>>16)&0xffff, *minor&0xffff));
714 /* Version info not found, fall back to origin date/time */
715 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
719 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
720 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
721 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
722 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
723 /* At this point, we assume the file is in error. It still could be somthing
724 * else besides a NE file, but it unlikely at this point. */
728 /* Allocate a bit more space to speed up things */
730 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
731 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
732 fname, PE_HEADER_SIZE));
736 /* This is a HACK! I got tired of trying to sort through the messy
737 * 'NE' file format. If anyone wants to clean this up please have at
738 * it, but this works. 'NE' files will eventually fade away. JRR */
739 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
740 /* Cover case that should not occur in a well formed 'NE' .dll file */
741 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
743 for(i=0; i<byte_count; i++) {
744 /* Fast skip past data that can't possibly match */
745 if (buf[i] != 'V') continue;
747 /* Potential match data crosses buf boundry, move it to beginning
748 * of buf, and fill the buf with as much as it will hold. */
749 if (i>byte_count-VS_VERSION_INFO_SIZE) {
752 memcpy(buf, &buf[i], byte_count-i);
753 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
754 (byte_count-i))) < 0) {
756 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
761 byte_count = bc + (byte_count - i);
762 if (byte_count<VS_VERSION_INFO_SIZE) break;
767 /* Check that the full signature string and the magic number that
768 * follows exist (not a perfect solution, but the chances that this
769 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
770 * twice, as it is simpler to read the code. */
771 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
772 /* Compute skip alignment to next long address */
773 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
774 sizeof(VS_SIGNATURE)) & 3;
775 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
777 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
778 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
779 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
780 fname, *major, *minor,
781 (*major>>16)&0xffff, *major&0xffff,
782 (*minor>>16)&0xffff, *minor&0xffff));
789 /* Version info not found, fall back to origin date/time */
790 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
795 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
796 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
797 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
808 /****************************************************************************
809 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
810 share one or more files. During the MS installation process files are checked
811 to insure that only a newer version of a shared file is installed over an
812 older version. There are several possibilities for this comparison. If there
813 is no previous version, the new one is newer (obviously). If either file is
814 missing the version info structure, compare the creation date (on Unix use
815 the modification date). Otherwise chose the numerically larger version number.
816 ****************************************************************************/
817 static int file_version_is_newer(connection_struct *conn, fstring new_file,
820 BOOL use_version = True;
825 time_t new_create_time;
829 time_t old_create_time;
833 files_struct *fsp = NULL;
835 SMB_STRUCT_STAT stat_buf;
839 ZERO_STRUCT(stat_buf);
840 new_create_time = (time_t)0;
841 old_create_time = (time_t)0;
843 /* Get file version info (if available) for previous file (if it exists) */
844 pstrcpy(filepath, old_file);
846 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
848 fsp = open_file_shared(conn, filepath, &stat_buf,
849 SET_OPEN_MODE(DOS_OPEN_RDONLY),
850 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
851 0, 0, &access_mode, &action);
853 /* Old file not found, so by definition new file is in fact newer */
854 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
859 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
860 if (ret == -1) goto error_exit;
863 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
866 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
867 old_create_time = st.st_mtime;
868 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
871 close_file(fsp, True);
873 /* Get file version info (if available) for new file */
874 pstrcpy(filepath, new_file);
875 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
877 fsp = open_file_shared(conn, filepath, &stat_buf,
878 SET_OPEN_MODE(DOS_OPEN_RDONLY),
879 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
880 0, 0, &access_mode, &action);
882 /* New file not found, this shouldn't occur if the caller did its job */
883 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
888 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
889 if (ret == -1) goto error_exit;
892 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
895 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
896 new_create_time = st.st_mtime;
897 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
900 close_file(fsp, True);
903 /* Compare versions and choose the larger version number */
904 if (new_major > old_major ||
905 (new_major == old_major && new_minor > old_minor)) {
907 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
911 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
916 /* Compare modification time/dates and choose the newest time/date */
917 if (new_create_time > old_create_time) {
918 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
922 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
929 close_file(fsp, True);
933 /****************************************************************************
934 Determine the correct cVersion associated with an architecture and driver
935 ****************************************************************************/
936 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
937 struct current_user *user, WERROR *perr)
945 files_struct *fsp = NULL;
948 connection_struct *conn;
952 *perr = WERR_INVALID_PARAM;
954 /* If architecture is Windows 95/98/ME, the version is always 0. */
955 if (strcmp(architecture, "WIN40") == 0) {
956 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
961 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
962 /* Null password is ok - we are already an authenticated user... */
963 null_pw = data_blob(NULL, 0);
966 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
970 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
971 *perr = ntstatus_to_werror(nt_status);
975 /* We are temporarily becoming the connection user. */
976 if (!become_user(conn, conn->vuid)) {
977 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
978 *perr = WERR_ACCESS_DENIED;
982 /* Open the driver file (Portable Executable format) and determine the
983 * deriver the cversion. */
984 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
986 unix_convert(driverpath,conn,NULL,&bad_path,&st);
988 fsp = open_file_shared(conn, driverpath, &st,
989 SET_OPEN_MODE(DOS_OPEN_RDONLY),
990 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
991 0, 0, &access_mode, &action);
993 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
995 *perr = WERR_ACCESS_DENIED;
1001 int ret = get_file_version(fsp, driverpath, &major, &minor);
1002 if (ret == -1) goto error_exit;
1005 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1010 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1011 * for more details. Version in this case is not just the version of the
1012 * file, but the version in the sense of kernal mode (2) vs. user mode
1013 * (3) drivers. Other bits of the version fields are the version info.
1016 cversion = major & 0x0000ffff;
1018 case 2: /* WinNT drivers */
1019 case 3: /* Win2K drivers */
1023 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1024 driverpath, cversion));
1028 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1029 driverpath, major, minor));
1032 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1033 driverpath, cversion));
1035 close_file(fsp, True);
1036 close_cnum(conn, user->vuid);
1044 close_file(fsp, True);
1046 close_cnum(conn, user->vuid);
1051 /****************************************************************************
1052 ****************************************************************************/
1053 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1054 struct current_user *user)
1056 fstring architecture;
1062 /* clean up the driver name.
1063 * we can get .\driver.dll
1064 * or worse c:\windows\system\driver.dll !
1066 /* using an intermediate string to not have overlaping memcpy()'s */
1067 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1068 fstrcpy(new_name, p+1);
1069 fstrcpy(driver->driverpath, new_name);
1072 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1073 fstrcpy(new_name, p+1);
1074 fstrcpy(driver->datafile, new_name);
1077 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1078 fstrcpy(new_name, p+1);
1079 fstrcpy(driver->configfile, new_name);
1082 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1083 fstrcpy(new_name, p+1);
1084 fstrcpy(driver->helpfile, new_name);
1087 if (driver->dependentfiles) {
1088 for (i=0; *driver->dependentfiles[i]; i++) {
1089 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1090 fstrcpy(new_name, p+1);
1091 fstrcpy(driver->dependentfiles[i], new_name);
1096 get_short_archi(architecture, driver->environment);
1098 /* jfm:7/16/2000 the client always sends the cversion=0.
1099 * The server should check which version the driver is by reading
1100 * the PE header of driver->driverpath.
1102 * For Windows 95/98 the version is 0 (so the value sent is correct)
1103 * For Windows NT (the architecture doesn't matter)
1104 * NT 3.1: cversion=0
1105 * NT 3.5/3.51: cversion=1
1109 if ((driver->cversion = get_correct_cversion( architecture,
1110 driver->driverpath, user, &err)) == -1)
1116 /****************************************************************************
1117 ****************************************************************************/
1118 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1119 struct current_user *user)
1121 fstring architecture;
1127 /* clean up the driver name.
1128 * we can get .\driver.dll
1129 * or worse c:\windows\system\driver.dll !
1131 /* using an intermediate string to not have overlaping memcpy()'s */
1132 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1133 fstrcpy(new_name, p+1);
1134 fstrcpy(driver->driverpath, new_name);
1137 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1138 fstrcpy(new_name, p+1);
1139 fstrcpy(driver->datafile, new_name);
1142 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1143 fstrcpy(new_name, p+1);
1144 fstrcpy(driver->configfile, new_name);
1147 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1148 fstrcpy(new_name, p+1);
1149 fstrcpy(driver->helpfile, new_name);
1152 if (driver->dependentfiles) {
1153 for (i=0; *driver->dependentfiles[i]; i++) {
1154 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1155 fstrcpy(new_name, p+1);
1156 fstrcpy(driver->dependentfiles[i], new_name);
1161 get_short_archi(architecture, driver->environment);
1163 /* jfm:7/16/2000 the client always sends the cversion=0.
1164 * The server should check which version the driver is by reading
1165 * the PE header of driver->driverpath.
1167 * For Windows 95/98 the version is 0 (so the value sent is correct)
1168 * For Windows NT (the architecture doesn't matter)
1169 * NT 3.1: cversion=0
1170 * NT 3.5/3.51: cversion=1
1174 if ((driver->version = get_correct_cversion(architecture,
1175 driver->driverpath, user, &err)) == -1)
1181 /****************************************************************************
1182 ****************************************************************************/
1183 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1184 uint32 level, struct current_user *user)
1189 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1190 driver=driver_abstract.info_3;
1191 return clean_up_driver_struct_level_3(driver, user);
1195 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1196 driver=driver_abstract.info_6;
1197 return clean_up_driver_struct_level_6(driver, user);
1200 return WERR_INVALID_PARAM;
1204 /****************************************************************************
1205 This function sucks and should be replaced. JRA.
1206 ****************************************************************************/
1208 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1210 dst->cversion = src->version;
1212 fstrcpy( dst->name, src->name);
1213 fstrcpy( dst->environment, src->environment);
1214 fstrcpy( dst->driverpath, src->driverpath);
1215 fstrcpy( dst->datafile, src->datafile);
1216 fstrcpy( dst->configfile, src->configfile);
1217 fstrcpy( dst->helpfile, src->helpfile);
1218 fstrcpy( dst->monitorname, src->monitorname);
1219 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1220 dst->dependentfiles = src->dependentfiles;
1223 #if 0 /* Debugging function */
1225 static char* ffmt(unsigned char *c){
1227 static char ffmt_str[17];
1229 for (i=0; i<16; i++) {
1230 if ((c[i] < ' ') || (c[i] > '~'))
1241 /****************************************************************************
1242 ****************************************************************************/
1243 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1244 struct current_user *user, WERROR *perr)
1246 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1247 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1248 fstring architecture;
1253 connection_struct *conn;
1261 driver=driver_abstract.info_3;
1262 else if (level==6) {
1263 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1264 driver = &converted_driver;
1266 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1270 get_short_archi(architecture, driver->environment);
1272 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1273 /* Null password is ok - we are already an authenticated user... */
1274 null_pw = data_blob(NULL, 0);
1275 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
1278 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1279 *perr = ntstatus_to_werror(nt_status);
1284 * Save who we are - we are temporarily becoming the connection user.
1289 if (!become_user(conn, conn->vuid)) {
1290 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1296 * make the directories version and version\driver_name
1297 * under the architecture directory.
1299 DEBUG(5,("Creating first directory\n"));
1300 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1301 mkdir_internal(conn, new_dir);
1303 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1304 * listed for this driver which has already been moved, skip it (note:
1305 * drivers may list the same file name several times. Then check if the
1306 * file already exists in archi\cversion\, if so, check that the version
1307 * info (or time stamps if version info is unavailable) is newer (or the
1308 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1309 * Otherwise, delete the file.
1311 * If a file is not moved to archi\cversion\ because of an error, all the
1312 * rest of the 'unmoved' driver files are removed from archi\. If one or
1313 * more of the driver's files was already moved to archi\cversion\, it
1314 * potentially leaves the driver in a partially updated state. Version
1315 * trauma will most likely occur if an client attempts to use any printer
1316 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1317 * done is appropriate... later JRR
1320 DEBUG(5,("Moving files now !\n"));
1322 if (driver->driverpath && strlen(driver->driverpath)) {
1323 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1324 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1325 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1327 status = rename_internals(conn, new_name, old_name, True);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1330 new_name, old_name));
1331 *perr = ntstatus_to_werror(status);
1332 unlink_internals(conn, 0, new_name);
1337 unlink_internals(conn, 0, new_name);
1340 if (driver->datafile && strlen(driver->datafile)) {
1341 if (!strequal(driver->datafile, driver->driverpath)) {
1342 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1343 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1344 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1346 status = rename_internals(conn, new_name, old_name, True);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1349 new_name, old_name));
1350 *perr = ntstatus_to_werror(status);
1351 unlink_internals(conn, 0, new_name);
1356 unlink_internals(conn, 0, new_name);
1360 if (driver->configfile && strlen(driver->configfile)) {
1361 if (!strequal(driver->configfile, driver->driverpath) &&
1362 !strequal(driver->configfile, driver->datafile)) {
1363 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1364 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1365 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1367 status = rename_internals(conn, new_name, old_name, True);
1368 if (!NT_STATUS_IS_OK(status)) {
1369 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1370 new_name, old_name));
1371 *perr = ntstatus_to_werror(status);
1372 unlink_internals(conn, 0, new_name);
1377 unlink_internals(conn, 0, new_name);
1381 if (driver->helpfile && strlen(driver->helpfile)) {
1382 if (!strequal(driver->helpfile, driver->driverpath) &&
1383 !strequal(driver->helpfile, driver->datafile) &&
1384 !strequal(driver->helpfile, driver->configfile)) {
1385 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1386 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1387 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1389 status = rename_internals(conn, new_name, old_name, True);
1390 if (!NT_STATUS_IS_OK(status)) {
1391 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1392 new_name, old_name));
1393 *perr = ntstatus_to_werror(status);
1394 unlink_internals(conn, 0, new_name);
1399 unlink_internals(conn, 0, new_name);
1403 if (driver->dependentfiles) {
1404 for (i=0; *driver->dependentfiles[i]; i++) {
1405 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1406 !strequal(driver->dependentfiles[i], driver->datafile) &&
1407 !strequal(driver->dependentfiles[i], driver->configfile) &&
1408 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1410 for (j=0; j < i; j++) {
1411 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1416 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1417 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1418 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1420 status = rename_internals(conn, new_name, old_name, True);
1421 if (!NT_STATUS_IS_OK(status)) {
1422 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1423 new_name, old_name));
1424 *perr = ntstatus_to_werror(status);
1425 unlink_internals(conn, 0, new_name);
1430 unlink_internals(conn, 0, new_name);
1436 close_cnum(conn, user->vuid);
1439 return ver == -1 ? False : True;
1442 /****************************************************************************
1443 ****************************************************************************/
1444 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1447 fstring architecture;
1453 TDB_DATA kbuf, dbuf;
1455 get_short_archi(architecture, driver->environment);
1457 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1458 * \\server is added in the rpc server layer.
1459 * It does make sense to NOT store the server's name in the printer TDB.
1462 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1464 /* .inf files do not always list a file for each of the four standard files.
1465 * Don't prepend a path to a null filename, or client claims:
1466 * "The server on which the printer resides does not have a suitable
1467 * <printer driver name> printer driver installed. Click OK if you
1468 * wish to install the driver on your local machine."
1470 if (strlen(driver->driverpath)) {
1471 fstrcpy(temp_name, driver->driverpath);
1472 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1475 if (strlen(driver->datafile)) {
1476 fstrcpy(temp_name, driver->datafile);
1477 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1480 if (strlen(driver->configfile)) {
1481 fstrcpy(temp_name, driver->configfile);
1482 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1485 if (strlen(driver->helpfile)) {
1486 fstrcpy(temp_name, driver->helpfile);
1487 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1490 if (driver->dependentfiles) {
1491 for (i=0; *driver->dependentfiles[i]; i++) {
1492 fstrcpy(temp_name, driver->dependentfiles[i]);
1493 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1497 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1499 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1506 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1509 driver->environment,
1514 driver->monitorname,
1515 driver->defaultdatatype);
1517 if (driver->dependentfiles) {
1518 for (i=0; *driver->dependentfiles[i]; i++) {
1519 len += tdb_pack(buf+len, buflen-len, "f",
1520 driver->dependentfiles[i]);
1524 if (len != buflen) {
1527 tb = (char *)Realloc(buf, len);
1529 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1540 kbuf.dsize = strlen(key)+1;
1544 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1548 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1554 /****************************************************************************
1555 ****************************************************************************/
1556 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1558 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1561 info3.cversion = driver->version;
1562 fstrcpy(info3.name,driver->name);
1563 fstrcpy(info3.environment,driver->environment);
1564 fstrcpy(info3.driverpath,driver->driverpath);
1565 fstrcpy(info3.datafile,driver->datafile);
1566 fstrcpy(info3.configfile,driver->configfile);
1567 fstrcpy(info3.helpfile,driver->helpfile);
1568 fstrcpy(info3.monitorname,driver->monitorname);
1569 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1570 info3.dependentfiles = driver->dependentfiles;
1572 return add_a_printer_driver_3(&info3);
1576 /****************************************************************************
1577 ****************************************************************************/
1578 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1580 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1584 fstrcpy(info.name, in_prt);
1585 fstrcpy(info.defaultdatatype, "RAW");
1587 fstrcpy(info.driverpath, "");
1588 fstrcpy(info.datafile, "");
1589 fstrcpy(info.configfile, "");
1590 fstrcpy(info.helpfile, "");
1592 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1595 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1596 fstrcpy(info.dependentfiles[0], "");
1598 *info_ptr = memdup(&info, sizeof(info));
1603 /****************************************************************************
1604 ****************************************************************************/
1605 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1607 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1608 TDB_DATA kbuf, dbuf;
1609 fstring architecture;
1614 ZERO_STRUCT(driver);
1616 get_short_archi(architecture, in_arch);
1618 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1620 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1623 kbuf.dsize = strlen(key)+1;
1625 dbuf = tdb_fetch(tdb_drivers, kbuf);
1627 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1629 if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1631 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1640 driver.defaultdatatype);
1643 while (len < dbuf.dsize) {
1646 tddfs = (fstring *)Realloc(driver.dependentfiles,
1647 sizeof(fstring)*(i+2));
1648 if (tddfs == NULL) {
1649 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1652 else driver.dependentfiles = tddfs;
1654 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1655 &driver.dependentfiles[i]);
1658 if (driver.dependentfiles != NULL)
1659 fstrcpy(driver.dependentfiles[i], "");
1661 SAFE_FREE(dbuf.dptr);
1663 if (len != dbuf.dsize) {
1664 SAFE_FREE(driver.dependentfiles);
1666 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1669 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1674 /****************************************************************************
1675 ****************************************************************************/
1676 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1678 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1684 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1685 DEBUG(10,("driver key: [%s]\n", key));
1688 kbuf.dsize = strlen(key)+1;
1689 if (!tdb_exists(tdb_drivers, kbuf)) return False;
1692 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1694 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1695 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1696 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1697 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1698 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1699 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1700 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1702 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1703 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1704 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1706 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1707 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1708 pstrcat(line, info3->configfile);
1710 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1711 pstrcat(line, info3->datafile);
1713 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1714 pstrcat(line, info3->helpfile);
1716 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1717 pstrcat(line, info3->monitorname);
1719 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1722 for (i=0; info3->dependentfiles &&
1723 *info3->dependentfiles[i]; i++) {
1724 if (i) pstrcat(line, ","); /* don't end in a "," */
1725 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1726 pstrcat(line, info3->dependentfiles[i]);
1734 /****************************************************************************
1735 debugging function, dump at level 6 the struct in the logs
1736 ****************************************************************************/
1737 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1740 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1743 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1749 if (driver.info_3 == NULL)
1752 info3=driver.info_3;
1754 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1755 DEBUGADD(106,("name:[%s]\n", info3->name));
1756 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1757 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1758 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1759 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1760 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1761 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1762 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1764 for (i=0; info3->dependentfiles &&
1765 *info3->dependentfiles[i]; i++) {
1766 DEBUGADD(106,("dependentfile:[%s]\n",
1767 info3->dependentfiles[i]));
1774 DEBUGADD(1,("Level not implemented\n"));
1782 /****************************************************************************
1783 ****************************************************************************/
1784 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1788 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1790 if (!nt_devmode) return len;
1792 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1793 nt_devmode->devicename,
1794 nt_devmode->formname,
1796 nt_devmode->specversion,
1797 nt_devmode->driverversion,
1799 nt_devmode->driverextra,
1800 nt_devmode->orientation,
1801 nt_devmode->papersize,
1802 nt_devmode->paperlength,
1803 nt_devmode->paperwidth,
1806 nt_devmode->defaultsource,
1807 nt_devmode->printquality,
1810 nt_devmode->yresolution,
1811 nt_devmode->ttoption,
1812 nt_devmode->collate,
1813 nt_devmode->logpixels,
1816 nt_devmode->bitsperpel,
1817 nt_devmode->pelswidth,
1818 nt_devmode->pelsheight,
1819 nt_devmode->displayflags,
1820 nt_devmode->displayfrequency,
1821 nt_devmode->icmmethod,
1822 nt_devmode->icmintent,
1823 nt_devmode->mediatype,
1824 nt_devmode->dithertype,
1825 nt_devmode->reserved1,
1826 nt_devmode->reserved2,
1827 nt_devmode->panningwidth,
1828 nt_devmode->panningheight,
1829 nt_devmode->private);
1832 if (nt_devmode->private) {
1833 len += tdb_pack(buf+len, buflen-len, "B",
1834 nt_devmode->driverextra,
1835 nt_devmode->private);
1838 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1843 /****************************************************************************
1844 ****************************************************************************/
1845 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1849 while (param != NULL) {
1850 len += tdb_pack(buf+len, buflen-len, "pfdB",
1859 len += tdb_pack(buf+len, buflen-len, "p", param);
1865 /****************************************************************************
1866 delete a printer - this just deletes the printer info file, any open
1867 handles are not affected
1868 ****************************************************************************/
1869 uint32 del_a_printer(char *sharename)
1874 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1877 kbuf.dsize=strlen(key)+1;
1879 tdb_delete(tdb_printers, kbuf);
1883 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1884 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1885 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1886 /****************************************************************************
1887 ****************************************************************************/
1888 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1894 TDB_DATA kbuf, dbuf;
1897 * in addprinter: no servername and the printer is the name
1898 * in setprinter: servername is \\server
1899 * and printer is \\server\\printer
1901 * Samba manages only local printers.
1902 * we currently don't support things like path=\\other_server\printer
1905 if (info->servername[0]!='\0') {
1906 trim_string(info->printername, info->servername, NULL);
1907 trim_string(info->printername, "\\", NULL);
1908 info->servername[0]='\0';
1912 * JFM: one day I'll forget.
1913 * below that's info->portname because that's the SAMBA sharename
1914 * and I made NT 'thinks' it's the portname
1915 * the info->sharename is the thing you can name when you add a printer
1916 * that's the short-name when you create shared printer for 95/98
1917 * So I've made a limitation in SAMBA: you can only have 1 printer model
1918 * behind a SAMBA share.
1926 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1929 info->default_priority,
1946 info->printprocessor,
1950 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1952 len += pack_specifics(info->specific, buf+len, buflen-len);
1954 if (buflen != len) {
1957 tb = (char *)Realloc(buf, len);
1959 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1969 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1972 kbuf.dsize = strlen(key)+1;
1976 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
1979 if (!W_ERROR_IS_OK(ret))
1980 DEBUG(8, ("error updating printer to tdb on disk\n"));
1984 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1985 info->sharename, info->drivername, info->portname, len));
1991 /****************************************************************************
1992 ****************************************************************************/
1993 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1995 NT_PRINTER_PARAM *current;
1997 DEBUG(108,("add_a_specific_param\n"));
1999 (*param)->next=NULL;
2001 if (info_2->specific == NULL)
2003 info_2->specific=*param;
2007 current=info_2->specific;
2008 while (current->next != NULL) {
2009 current=current->next;
2011 current->next=*param;
2017 /****************************************************************************
2018 ****************************************************************************/
2019 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2021 NT_PRINTER_PARAM *current;
2022 NT_PRINTER_PARAM *previous;
2024 current=info_2->specific;
2027 if (current==NULL) return (False);
2029 if ( !strcmp(current->value, param->value) &&
2030 (strlen(current->value)==strlen(param->value)) ) {
2031 DEBUG(109,("deleting first value\n"));
2032 info_2->specific=current->next;
2033 SAFE_FREE(current->data);
2035 DEBUG(109,("deleted first value\n"));
2039 current=previous->next;
2041 while ( current!=NULL ) {
2042 if (!strcmp(current->value, param->value) &&
2043 strlen(current->value)==strlen(param->value) ) {
2044 DEBUG(109,("deleting current value\n"));
2045 previous->next=current->next;
2046 SAFE_FREE(current->data);
2048 DEBUG(109,("deleted current value\n"));
2052 previous=previous->next;
2053 current=current->next;
2058 /****************************************************************************
2059 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2060 ****************************************************************************/
2061 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2063 NT_PRINTER_PARAM *param = *param_ptr;
2068 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2070 SAFE_FREE(param->data);
2071 SAFE_FREE(*param_ptr);
2074 /****************************************************************************
2075 Malloc and return an NT devicemode.
2076 ****************************************************************************/
2078 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2081 * should I init this ones ???
2082 nt_devmode->devicename
2086 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2088 if (nt_devmode == NULL) {
2089 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2093 ZERO_STRUCTP(nt_devmode);
2095 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2096 fstrcpy(nt_devmode->devicename, adevice);
2098 fstrcpy(nt_devmode->formname, "Letter");
2100 nt_devmode->specversion = 0x0401;
2101 nt_devmode->driverversion = 0x0400;
2102 nt_devmode->size = 0x00DC;
2103 nt_devmode->driverextra = 0x0000;
2104 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2105 DEFAULTSOURCE | COPIES | SCALE |
2106 PAPERSIZE | ORIENTATION;
2107 nt_devmode->orientation = 1;
2108 nt_devmode->papersize = PAPER_LETTER;
2109 nt_devmode->paperlength = 0;
2110 nt_devmode->paperwidth = 0;
2111 nt_devmode->scale = 0x64;
2112 nt_devmode->copies = 1;
2113 nt_devmode->defaultsource = BIN_FORMSOURCE;
2114 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2115 nt_devmode->color = COLOR_MONOCHROME;
2116 nt_devmode->duplex = DUP_SIMPLEX;
2117 nt_devmode->yresolution = 0;
2118 nt_devmode->ttoption = TT_SUBDEV;
2119 nt_devmode->collate = COLLATE_FALSE;
2120 nt_devmode->icmmethod = 0;
2121 nt_devmode->icmintent = 0;
2122 nt_devmode->mediatype = 0;
2123 nt_devmode->dithertype = 0;
2125 /* non utilisés par un driver d'imprimante */
2126 nt_devmode->logpixels = 0;
2127 nt_devmode->bitsperpel = 0;
2128 nt_devmode->pelswidth = 0;
2129 nt_devmode->pelsheight = 0;
2130 nt_devmode->displayflags = 0;
2131 nt_devmode->displayfrequency = 0;
2132 nt_devmode->reserved1 = 0;
2133 nt_devmode->reserved2 = 0;
2134 nt_devmode->panningwidth = 0;
2135 nt_devmode->panningheight = 0;
2137 nt_devmode->private = NULL;
2141 /****************************************************************************
2142 Deepcopy an NT devicemode.
2143 ****************************************************************************/
2145 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2147 NT_DEVICEMODE *new_nt_devicemode = NULL;
2149 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2150 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2154 new_nt_devicemode->private = NULL;
2155 if (nt_devicemode->private != NULL) {
2156 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2157 SAFE_FREE(new_nt_devicemode);
2158 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2163 return new_nt_devicemode;
2166 /****************************************************************************
2167 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2168 ****************************************************************************/
2170 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2172 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2174 if(nt_devmode == NULL)
2177 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2179 SAFE_FREE(nt_devmode->private);
2180 SAFE_FREE(*devmode_ptr);
2183 /****************************************************************************
2184 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2185 ****************************************************************************/
2186 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2188 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2189 NT_PRINTER_PARAM *param_ptr;
2194 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2196 free_nt_devicemode(&info->devmode);
2198 for(param_ptr = info->specific; param_ptr; ) {
2199 NT_PRINTER_PARAM *tofree = param_ptr;
2201 param_ptr = param_ptr->next;
2202 free_nt_printer_param(&tofree);
2205 SAFE_FREE(*info_ptr);
2209 /****************************************************************************
2210 ****************************************************************************/
2211 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2215 NT_DEVICEMODE devmode;
2217 ZERO_STRUCT(devmode);
2219 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2221 if (!*nt_devmode) return len;
2223 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2227 &devmode.specversion,
2228 &devmode.driverversion,
2230 &devmode.driverextra,
2231 &devmode.orientation,
2233 &devmode.paperlength,
2234 &devmode.paperwidth,
2237 &devmode.defaultsource,
2238 &devmode.printquality,
2241 &devmode.yresolution,
2247 &devmode.bitsperpel,
2249 &devmode.pelsheight,
2250 &devmode.displayflags,
2251 &devmode.displayfrequency,
2255 &devmode.dithertype,
2258 &devmode.panningwidth,
2259 &devmode.panningheight,
2262 if (devmode.private) {
2263 /* the len in tdb_unpack is an int value and
2264 * devmode.driverextra is only a short
2266 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2267 devmode.driverextra=(uint16)extra_len;
2269 /* check to catch an invalid TDB entry so we don't segfault */
2270 if (devmode.driverextra == 0) {
2271 devmode.private = NULL;
2275 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2277 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2278 if (devmode.private)
2279 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2284 /****************************************************************************
2285 ****************************************************************************/
2286 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2289 NT_PRINTER_PARAM param, *p;
2294 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2297 len += tdb_unpack(buf+len, buflen-len, "fdB",
2303 *list = memdup(¶m, sizeof(param));
2305 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2311 static void map_to_os2_driver(fstring drivername)
2313 static BOOL initialised=False;
2314 static fstring last_from,last_to;
2315 char *mapfile = lp_os2_driver_map();
2316 char **lines = NULL;
2320 if (!strlen(drivername))
2327 *last_from = *last_to = 0;
2331 if (strequal(drivername,last_from)) {
2332 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2333 fstrcpy(drivername,last_to);
2337 lines = file_lines_load(mapfile, &numlines);
2338 if (numlines == 0) {
2339 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2343 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2345 for( i = 0; i < numlines; i++) {
2346 char *nt_name = lines[i];
2347 char *os2_name = strchr(nt_name,'=');
2354 while (isspace(*nt_name))
2357 if (!*nt_name || strchr("#;",*nt_name))
2361 int l = strlen(nt_name);
2362 while (l && isspace(nt_name[l-1])) {
2368 while (isspace(*os2_name))
2372 int l = strlen(os2_name);
2373 while (l && isspace(os2_name[l-1])) {
2379 if (strequal(nt_name,drivername)) {
2380 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2381 fstrcpy(last_from,drivername);
2382 fstrcpy(last_to,os2_name);
2383 fstrcpy(drivername,os2_name);
2384 file_lines_free(lines);
2389 file_lines_free(lines);
2392 /****************************************************************************
2393 get a default printer info 2 struct
2394 ****************************************************************************/
2395 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2398 NT_PRINTER_INFO_LEVEL_2 info;
2402 snum = lp_servicenumber(sharename);
2404 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2405 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2406 get_called_name(), sharename);
2407 fstrcpy(info.sharename, sharename);
2408 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2409 fstrcpy(info.drivername, lp_printerdriver(snum));
2411 /* by setting the driver name to an empty string, a local NT admin
2412 can now run the **local** APW to install a local printer driver
2413 for a Samba shared printer in 2.2. Without this, drivers **must** be
2414 installed on the Samba server for NT clients --jerry */
2415 #if 0 /* JERRY --do not uncomment-- */
2416 if (!*info.drivername)
2417 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2421 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2423 pstrcpy(info.comment, "");
2424 fstrcpy(info.printprocessor, "winprint");
2425 fstrcpy(info.datatype, "RAW");
2427 info.attributes = (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2429 info.starttime = 0; /* Minutes since 12:00am GMT */
2430 info.untiltime = 0; /* Minutes since 12:00am GMT */
2432 info.default_priority = 1;
2433 info.setuptime = (uint32)time(NULL) - 86400; /* minus 1 day */
2436 * I changed this as I think it is better to have a generic
2437 * DEVMODE than to crash Win2k explorer.exe --jerry
2438 * See the HP Deskjet 990c Win2k drivers for an example.
2440 * However the default devmode appears to cause problems
2441 * with the HP CLJ 8500 PCL driver. Hence the addition of
2442 * the "default devmode" parameter --jerry 22/01/2002
2445 if (lp_default_devmode(snum)) {
2446 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2450 info.devmode = NULL;
2453 /* This will get the current RPC talloc context, but we should be
2454 passing this as a parameter... fixme... JRA ! */
2456 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2459 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2461 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2470 free_nt_devicemode(&info.devmode);
2471 return WERR_ACCESS_DENIED;
2474 /****************************************************************************
2475 ****************************************************************************/
2476 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2479 NT_PRINTER_INFO_LEVEL_2 info;
2481 TDB_DATA kbuf, dbuf;
2482 fstring printername;
2486 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2489 kbuf.dsize = strlen(key)+1;
2491 dbuf = tdb_fetch(tdb_printers, kbuf);
2493 return get_a_printer_2_default(info_ptr, sharename);
2495 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2498 &info.default_priority,
2515 info.printprocessor,
2519 /* Samba has to have shared raw drivers. */
2520 info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2522 /* Restore the stripped strings. */
2523 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2524 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2526 fstrcpy(info.printername, printername);
2528 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2531 * Some client drivers freak out if there is a NULL devmode
2532 * (probably the driver is not checking before accessing
2533 * the devmode pointer) --jerry
2535 * See comments in get_a_printer_2_default()
2538 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2540 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2542 info.devmode = construct_nt_devicemode(printername);
2545 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2547 /* This will get the current RPC talloc context, but we should be
2548 passing this as a parameter... fixme... JRA ! */
2550 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2552 /* Fix for OS/2 drivers. */
2554 if (get_remote_arch() == RA_OS2)
2555 map_to_os2_driver(info.drivername);
2557 SAFE_FREE(dbuf.dptr);
2558 *info_ptr=memdup(&info, sizeof(info));
2560 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2561 sharename, info.printername, info.drivername));
2566 /****************************************************************************
2567 debugging function, dump at level 6 the struct in the logs
2568 ****************************************************************************/
2569 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2572 NT_PRINTER_INFO_LEVEL_2 *info2;
2574 DEBUG(106,("Dumping printer at level [%d]\n", level));
2580 if (printer.info_2 == NULL)
2584 info2=printer.info_2;
2586 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2587 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2588 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2589 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2590 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2591 DEBUGADD(106,("status:[%d]\n", info2->status));
2592 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2593 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2594 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2595 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2596 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2598 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2599 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2600 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2601 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2602 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2603 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2604 DEBUGADD(106,("location:[%s]\n", info2->location));
2605 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2606 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2607 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2608 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2614 DEBUGADD(1,("Level not implemented\n"));
2622 /****************************************************************************
2623 Get the parameters we can substitute in an NT print job.
2624 ****************************************************************************/
2626 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2628 NT_PRINTER_INFO_LEVEL *printer = NULL;
2630 **printername = **sharename = **portname = '\0';
2632 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2635 fstrcpy(*printername, printer->info_2->printername);
2636 fstrcpy(*sharename, printer->info_2->sharename);
2637 fstrcpy(*portname, printer->info_2->portname);
2639 free_a_printer(&printer, 2);
2642 /****************************************************************************
2643 Update the changeid time.
2644 This is SO NASTY as some drivers need this to change, others need it
2645 static. This value will change every second, and I must hope that this
2646 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2648 ****************************************************************************/
2650 static uint32 rev_changeid(void)
2654 get_process_uptime(&tv);
2655 /* This value is in ms * 100 */
2656 return (((tv.tv_sec * 1000000) + tv.tv_usec)/100);
2660 * The function below are the high level ones.
2661 * only those ones must be called from the spoolss code.
2665 /****************************************************************************
2666 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2667 ****************************************************************************/
2669 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2673 dump_a_printer(printer, level);
2680 * Update the changestamp. Emperical tests show that the
2681 * ChangeID is always updated,but c_setprinter is only
2682 * incremented on a SetPrinter() call.
2685 /* ChangeID **must** be increasing over the lifetime
2686 of client's spoolss service in order for the
2687 client's cache to show updates */
2689 printer.info_2->changeid = rev_changeid();
2692 * Because one day someone will ask:
2693 * NT->NT An admin connection to a remote
2694 * printer show changes imeediately in
2695 * the properities dialog
2697 * A non-admin connection will only show the
2698 * changes after viewing the properites page
2699 * 2 times. Seems to be related to a
2700 * race condition in the client between the spooler
2701 * updating the local cache and the Explorer.exe GUI
2702 * actually displaying the properties.
2704 * This is fixed in Win2k. admin/non-admin
2705 * connections both display changes immediately.
2710 result=update_a_printer_2(printer.info_2);
2714 result=WERR_UNKNOWN_LEVEL;
2721 /****************************************************************************
2722 Initialize printer devmode & data with previously saved driver init values.
2723 ****************************************************************************/
2724 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2728 TDB_DATA kbuf, dbuf;
2729 NT_PRINTER_PARAM *current;
2730 NT_PRINTER_INFO_LEVEL_2 info;
2734 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2737 kbuf.dsize = strlen(key)+1;
2739 dbuf = tdb_fetch(tdb_drivers, kbuf);
2744 * Get the saved DEVMODE..
2746 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2749 * The saved DEVMODE contains the devicename from the printer used during
2750 * the initialization save. Change it to reflect the new printer.
2752 ZERO_STRUCT(info.devmode->devicename);
2753 fstrcpy(info.devmode->devicename, info_ptr->printername);
2756 * Bind the saved DEVMODE to the new the printer.
2758 free_nt_devicemode(&info_ptr->devmode);
2759 info_ptr->devmode = info.devmode;
2761 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2762 info_ptr->printername, info_ptr->drivername));
2765 * There should not be any printer data 'specifics' already set during the
2766 * add printer operation, if there are delete them.
2768 while ( (current=info_ptr->specific) != NULL ) {
2769 info_ptr->specific=current->next;
2770 SAFE_FREE(current->data);
2775 * Add the printer data 'specifics' to the new printer
2777 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2779 SAFE_FREE(dbuf.dptr);
2784 /****************************************************************************
2785 Initialize printer devmode & data with previously saved driver init values.
2786 When a printer is created using AddPrinter, the drivername bound to the
2787 printer is used to lookup previously saved driver initialization info, which
2788 is bound to the new printer.
2789 ****************************************************************************/
2791 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2799 result=set_driver_init_2(printer->info_2);
2810 /****************************************************************************
2811 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2812 in the tdb. Note: this is different from the driver entry and the printer
2813 entry. There should be a single driver init entry for each driver regardless
2814 of whether it was installed from NT or 2K. Technically, they should be
2815 different, but they work out to the same struct.
2816 ****************************************************************************/
2817 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2821 int buflen, len, ret;
2822 TDB_DATA kbuf, dbuf;
2829 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2831 len += pack_specifics(info->specific, buf+len, buflen-len);
2833 if (buflen != len) {
2836 tb = (char *)Realloc(buf, len);
2838 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2847 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2850 kbuf.dsize = strlen(key)+1;
2854 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2858 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2862 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2863 info->sharename, info->drivername));
2868 /****************************************************************************
2869 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2870 ****************************************************************************/
2872 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2876 dump_a_printer(printer, level);
2882 result=update_driver_init_2(printer.info_2);
2893 /****************************************************************************
2894 Convert the printer data value, a REG_BINARY array, into an initialization
2895 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2896 got to keep the endians happy :).
2897 ****************************************************************************/
2899 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2901 BOOL result = False;
2905 ZERO_STRUCT(devmode);
2907 prs_init(&ps, 0, ctx, UNMARSHALL);
2908 ps.data_p = (char *)param->data;
2909 ps.buffer_size = param->data_len;
2911 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2912 result = convert_devicemode("", &devmode, &nt_devmode);
2914 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2919 /****************************************************************************
2920 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2922 1. Use the driver's config DLL to this UNC printername and:
2923 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2924 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2925 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2927 The last step triggers saving the "driver initialization" information for
2928 this printer into the tdb. Later, new printers that use this driver will
2929 have this initialization information bound to them. This simulates the
2930 driver initialization, as if it had run on the Samba server (as it would
2933 The Win32 client side code requirement sucks! But until we can run arbitrary
2934 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2936 It would have been easier to use SetPrinter because all the UNMARSHALLING of
2937 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2938 about it and you will realize why. JRR 010720
2939 ****************************************************************************/
2941 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2943 WERROR status = WERR_OK;
2944 TALLOC_CTX *ctx = NULL;
2945 NT_DEVICEMODE *nt_devmode = NULL;
2946 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2949 * Set devmode on printer info, so entire printer initialization can be
2952 if ((ctx = talloc_init()) == NULL)
2955 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2956 status = WERR_NOMEM;
2960 ZERO_STRUCTP(nt_devmode);
2963 * The DEVMODE is held in the 'data' component of the param in raw binary.
2964 * Convert it to to a devmode structure
2966 if (!convert_driver_init(param, ctx, nt_devmode)) {
2967 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
2968 status = WERR_INVALID_PARAM;
2973 * Pack up and add (or update) the DEVMODE and any current printer data to
2974 * a 'driver init' element in the tdb
2977 printer->info_2->devmode = nt_devmode;
2978 if (update_driver_init(*printer, 2)!=0) {
2979 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
2980 status = WERR_NOMEM;
2985 * If driver initialization info was successfully saved, set the current
2986 * printer to match it. This allows initialization of the current printer
2987 * as well as the driver.
2989 status = mod_a_printer(*printer, 2);
2990 if (!W_ERROR_IS_OK(status)) {
2991 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
2992 printer->info_2->printername));
2996 talloc_destroy(ctx);
2998 SAFE_FREE(nt_devmode->private);
2999 SAFE_FREE(nt_devmode);
3000 printer->info_2->devmode = tmp_devmode;
3005 /****************************************************************************
3006 Update the driver init info (DEVMODE and specifics) for a printer
3007 ****************************************************************************/
3009 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3011 WERROR status = WERR_OK;
3017 status=save_driver_init_2(printer, param);
3021 status=WERR_UNKNOWN_LEVEL;
3028 /****************************************************************************
3029 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3030 ****************************************************************************/
3032 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3035 NT_PRINTER_INFO_LEVEL *printer = NULL;
3039 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3045 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3046 DEBUG(0,("get_a_printer: malloc fail.\n"));
3049 ZERO_STRUCTP(printer);
3050 result=get_a_printer_2(&printer->info_2, sharename);
3051 if (W_ERROR_IS_OK(result)) {
3052 dump_a_printer(*printer, level);
3053 *pp_printer = printer;
3060 result=WERR_UNKNOWN_LEVEL;
3064 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, werror_str(result)));
3069 /****************************************************************************
3070 Deletes a NT_PRINTER_INFO_LEVEL struct.
3071 ****************************************************************************/
3073 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3076 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3078 DEBUG(104,("freeing a printer at level [%d]\n", level));
3080 if (printer == NULL)
3087 if (printer->info_2 != NULL)
3089 free_nt_printer_info_level_2(&printer->info_2);
3103 SAFE_FREE(*pp_printer);
3107 /****************************************************************************
3108 ****************************************************************************/
3109 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3112 DEBUG(104,("adding a printer at level [%d]\n", level));
3113 dump_a_printer_driver(driver, level);
3119 result=add_a_printer_driver_3(driver.info_3);
3125 result=add_a_printer_driver_6(driver.info_6);
3135 /****************************************************************************
3136 ****************************************************************************/
3137 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3138 fstring printername, fstring architecture, uint32 version)
3146 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3154 if (W_ERROR_IS_OK(result))
3155 dump_a_printer_driver(*driver, level);
3159 /****************************************************************************
3160 ****************************************************************************/
3161 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3169 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3170 if (driver.info_3 != NULL)
3172 info3=driver.info_3;
3173 SAFE_FREE(info3->dependentfiles);
3174 ZERO_STRUCTP(info3);
3186 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3187 if (driver.info_6 != NULL)
3189 info6=driver.info_6;
3190 SAFE_FREE(info6->dependentfiles);
3191 SAFE_FREE(info6->previousnames);
3192 ZERO_STRUCTP(info6);
3210 /****************************************************************************
3211 Determine whether or not a particular driver is currently assigned
3213 ****************************************************************************/
3214 BOOL printer_driver_in_use (char *arch, char *driver)
3216 TDB_DATA kbuf, newkey, dbuf;
3217 NT_PRINTER_INFO_LEVEL_2 info;
3221 if (!nt_printing_init())
3224 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3226 /* loop through the printers.tdb and check for the drivername */
3227 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3228 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3231 dbuf = tdb_fetch(tdb_printers, kbuf);
3235 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3238 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3241 &info.default_priority,
3258 info.printprocessor,
3262 SAFE_FREE(dbuf.dptr);
3265 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3270 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3271 info.printername, info.drivername));
3273 if (strcmp(info.drivername, driver) == 0)
3275 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3276 info.printername, driver));
3280 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3284 /* report that the driver is in use by default */
3288 /****************************************************************************
3289 Remove a printer driver from the TDB. This assumes that the the driver was
3290 previously looked up.
3291 ***************************************************************************/
3292 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3299 get_short_archi(arch, i->environment);
3300 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3301 arch, i->cversion, i->name);
3302 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3305 kbuf.dsize=strlen(key)+1;
3307 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3308 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3309 return WERR_ACCESS_DENIED;
3312 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3317 /****************************************************************************
3318 ****************************************************************************/
3319 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3320 fstring value, uint8 **data, uint32 *type, uint32 *len)
3322 /* right now that's enough ! */
3323 NT_PRINTER_PARAM *param;
3326 param=printer.info_2->specific;
3328 while (param != NULL && i < param_index) {
3336 /* exited because it exist */
3338 StrnCpy(value, param->value, sizeof(fstring)-1);
3339 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3342 ZERO_STRUCTP(*data);
3343 memcpy(*data, param->data, param->data_len);
3344 *len=param->data_len;
3348 /****************************************************************************
3349 ****************************************************************************/
3350 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3351 fstring value, uint8 **data, uint32 *type, uint32 *len)
3353 /* right now that's enough ! */
3354 NT_PRINTER_PARAM *param;
3356 DEBUG(10, ("get_specific_param\n"));
3358 param=printer.info_2->specific;
3360 while (param != NULL)
3362 #if 1 /* JRA - I think this should be case insensitive.... */
3363 if ( strequal(value, param->value)
3365 if ( !strcmp(value, param->value)
3367 && strlen(value)==strlen(param->value))
3375 DEBUGADD(10, ("get_specific_param: found one param\n"));
3376 /* exited because it exist */
3379 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3382 memcpy(*data, param->data, param->data_len);
3383 *len=param->data_len;
3385 DEBUGADD(10, ("get_specific_param: exit true\n"));
3388 DEBUGADD(10, ("get_specific_param: exit false\n"));
3392 /****************************************************************************
3393 Store a security desc for a printer.
3394 ****************************************************************************/
3396 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3398 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3399 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3401 TALLOC_CTX *mem_ctx = NULL;
3405 mem_ctx = talloc_init();
3406 if (mem_ctx == NULL)
3409 /* The old owner and group sids of the security descriptor are not
3410 present when new ACEs are added or removed by changing printer
3411 permissions through NT. If they are NULL in the new security
3412 descriptor then copy them over from the old one. */
3414 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3415 DOM_SID *owner_sid, *group_sid;
3416 SEC_ACL *dacl, *sacl;
3417 SEC_DESC *psd = NULL;
3420 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3422 /* Pick out correct owner and group sids */
3424 owner_sid = secdesc_ctr->sec->owner_sid ?
3425 secdesc_ctr->sec->owner_sid :
3426 old_secdesc_ctr->sec->owner_sid;
3428 group_sid = secdesc_ctr->sec->grp_sid ?
3429 secdesc_ctr->sec->grp_sid :
3430 old_secdesc_ctr->sec->grp_sid;
3432 dacl = secdesc_ctr->sec->dacl ?
3433 secdesc_ctr->sec->dacl :
3434 old_secdesc_ctr->sec->dacl;
3436 sacl = secdesc_ctr->sec->sacl ?
3437 secdesc_ctr->sec->sacl :
3438 old_secdesc_ctr->sec->sacl;
3440 /* Make a deep copy of the security descriptor */
3442 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3443 owner_sid, group_sid,
3448 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3451 if (!new_secdesc_ctr) {
3452 new_secdesc_ctr = secdesc_ctr;
3455 /* Store the security descriptor in a tdb */
3457 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3458 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3460 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3462 status = WERR_BADFUNC;
3466 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3468 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3471 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3472 status = WERR_BADFUNC;
3475 /* Free malloc'ed memory */
3481 talloc_destroy(mem_ctx);
3485 /****************************************************************************
3486 Construct a default security descriptor buffer for a printer.
3487 ****************************************************************************/
3489 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3493 SEC_ACL *psa = NULL;
3494 SEC_DESC_BUF *sdb = NULL;
3495 SEC_DESC *psd = NULL;
3499 /* Create an ACE where Everyone is allowed to print */
3501 init_sec_access(&sa, PRINTER_ACE_PRINT);
3502 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3503 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3505 /* Make the security descriptor owned by the Administrators group
3506 on the PDC of the domain. */
3508 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
3509 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3511 /* Backup plan - make printer owned by admins.
3512 This should emulate a lanman printer as security
3513 settings can't be changed. */
3515 sid_copy(&owner_sid, &global_sam_sid);
3516 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3519 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3520 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3521 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3522 SEC_ACE_FLAG_INHERIT_ONLY);
3524 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3525 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3526 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3528 /* The ACL revision number in rpc_secdesc.h differs from the one
3529 created by NT when setting ACE entries in printer
3530 descriptors. NT4 complains about the property being edited by a
3533 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3534 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3536 NULL, psa, &sd_size);
3540 DEBUG(0,("construct_default_printer_sdb: Failed to make SEC_DESC.\n"));
3544 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3546 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3547 (unsigned int)sd_size));
3552 /****************************************************************************
3553 Get a security desc for a printer.
3554 ****************************************************************************/
3556 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3562 if ((temp = strchr(printername + 2, '\\'))) {
3563 printername = temp + 1;
3566 /* Fetch security descriptor from tdb */
3568 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3570 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3571 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3573 DEBUG(4,("using default secdesc for %s\n", printername));
3575 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3579 /* Save default security descriptor for later */
3581 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
3582 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
3584 if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
3585 tdb_prs_store(tdb_printers, key, &ps);
3592 /* If security descriptor is owned by S-1-1-0 and we can now read our
3593 domain sid (from secrets.tdb). The current security descriptor must of been
3594 created under the old code that didn't talk to winbind properly or when winbindd was
3595 down. Take ownership of security descriptor. */
3597 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3600 /* Change sd owner to workgroup administrator */
3602 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
3603 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3604 SEC_DESC *psd = NULL;
3609 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3611 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3613 (*secdesc_ctr)->sec->grp_sid,
3614 (*secdesc_ctr)->sec->sacl,
3615 (*secdesc_ctr)->sec->dacl,
3618 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3620 /* Swap with other one */
3622 *secdesc_ctr = new_secdesc_ctr;
3626 nt_printing_setsec(printername, *secdesc_ctr);
3630 if (DEBUGLEVEL >= 10) {
3631 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3634 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3635 printername, the_acl->num_aces));
3637 for (i = 0; i < the_acl->num_aces; i++) {
3640 sid_to_string(sid_str, &the_acl->ace[i].trustee);
3642 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3643 the_acl->ace[i].type, the_acl->ace[i].flags,
3644 the_acl->ace[i].info.mask));
3654 1: level not implemented
3655 2: file doesn't exist
3656 3: can't allocate memory
3657 4: can't free memory
3658 5: non existant struct
3662 A printer and a printer driver are 2 different things.
3663 NT manages them separatelly, Samba does the same.
3664 Why ? Simply because it's easier and it makes sense !
3666 Now explanation: You have 3 printers behind your samba server,
3667 2 of them are the same make and model (laser A and B). But laser B
3668 has an 3000 sheet feeder and laser A doesn't such an option.
3669 Your third printer is an old dot-matrix model for the accounting :-).
3671 If the /usr/local/samba/lib directory (default dir), you will have
3672 5 files to describe all of this.
3674 3 files for the printers (1 by printer):
3677 NTprinter_accounting
3678 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3679 NTdriver_printer model X
3680 NTdriver_printer model Y
3682 jfm: I should use this comment for the text file to explain
3683 same thing for the forms BTW.
3684 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3688 /* Convert generic access rights to printer object specific access rights.
3689 It turns out that NT4 security descriptors use generic access rights and
3690 NT5 the object specific ones. */
3692 void map_printer_permissions(SEC_DESC *sd)
3696 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3697 se_map_generic(&sd->dacl->ace[i].info.mask,
3698 &printer_generic_mapping);
3702 /****************************************************************************
3703 Check a user has permissions to perform the given operation. We use the
3704 permission constants defined in include/rpc_spoolss.h to check the various
3705 actions we perform when checking printer access.
3707 PRINTER_ACCESS_ADMINISTER:
3708 print_queue_pause, print_queue_resume, update_printer_sec,
3709 update_printer, spoolss_addprinterex_level_2,
3710 _spoolss_setprinterdata
3715 JOB_ACCESS_ADMINISTER:
3716 print_job_delete, print_job_pause, print_job_resume,
3719 ****************************************************************************/
3720 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3722 SEC_DESC_BUF *secdesc = NULL;
3723 uint32 access_granted;
3727 TALLOC_CTX *mem_ctx = NULL;
3728 extern struct current_user current_user;
3730 /* If user is NULL then use the current_user structure */
3733 user = ¤t_user;
3735 /* Always allow root or printer admins to do anything */
3737 if (user->uid == 0 ||
3738 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3742 /* Get printer name */
3744 pname = PRINTERNAME(snum);
3746 if (!pname || !*pname) {
3751 /* Get printer security descriptor */
3753 if(!(mem_ctx = talloc_init())) {
3758 nt_printing_getsec(mem_ctx, pname, &secdesc);
3760 if (access_type == JOB_ACCESS_ADMINISTER) {
3761 SEC_DESC_BUF *parent_secdesc = secdesc;
3763 /* Create a child security descriptor to check permissions
3764 against. This is because print jobs are child objects
3765 objects of a printer. */
3767 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3769 /* Now this is the bit that really confuses me. The access
3770 type needs to be changed from JOB_ACCESS_ADMINISTER to
3771 PRINTER_ACCESS_ADMINISTER for this to work. Something
3772 to do with the child (job) object becoming like a
3775 access_type = PRINTER_ACCESS_ADMINISTER;
3780 map_printer_permissions(secdesc->sec);
3782 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
3783 &access_granted, &status);
3785 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3787 talloc_destroy(mem_ctx);
3795 /****************************************************************************
3796 Check the time parameters allow a print operation.
3797 *****************************************************************************/
3799 BOOL print_time_access_check(int snum)
3801 NT_PRINTER_INFO_LEVEL *printer = NULL;
3803 time_t now = time(NULL);
3807 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3810 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3814 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3816 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3819 free_a_printer(&printer, 2);
3827 /****************************************************************************
3828 Attempt to write a default device.
3829 *****************************************************************************/
3831 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3833 NT_PRINTER_INFO_LEVEL *printer = NULL;
3837 * Don't bother if no default devicemode was sent.
3840 if (printer_default->devmode_cont.devmode == NULL)
3843 result = get_a_printer(&printer, 2, lp_servicename(snum));
3844 if (!W_ERROR_IS_OK(result)) return result;
3847 * Just ignore it if we already have a devmode.
3850 if (printer->info_2->devmode != NULL)
3854 * We don't have a devicemode and we're trying to write
3855 * one. Check we have the access needed.
3857 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3859 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3860 PRINTER_ACCESS_ADMINISTER) {
3861 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3862 result = WERR_ACCESS_DENIED;
3866 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3867 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3868 lp_servicename(snum) ));
3869 result = WERR_ACCESS_DENIED;
3870 /*result = NT_STATUS_NO_PROBLEMO;*/
3874 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3877 * Convert the on the wire devicemode format to the internal one.
3880 if (!convert_devicemode(printer->info_2->printername,
3881 printer_default->devmode_cont.devmode,
3882 &printer->info_2->devmode)) {
3883 result = WERR_NOMEM;
3888 * Finally write back to the tdb.
3891 result = mod_a_printer(*printer, 2);
3895 free_a_printer(&printer, 2);