2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern pstring global_myname;
26 extern DOM_SID global_sid_World;
28 static TDB_CONTEXT *tdb_forms; /* used for forms files */
29 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
30 static TDB_CONTEXT *tdb_printers; /* used for printers files */
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
35 #define PRINTERS_PREFIX "PRINTERS/"
36 #define SECDESC_PREFIX "SECDESC/"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
41 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_2
43 /* Map generic permissions to printer object specific permissions */
45 struct generic_mapping printer_generic_mapping = {
52 /* We need one default form to support our default printer. Msoft adds the
53 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
54 array index). Letter is always first, so (for the current code) additions
55 always put things in the correct order. */
56 static nt_forms_struct default_forms[] = {
57 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
58 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
59 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
60 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
61 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
62 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
63 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
64 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
65 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
66 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
67 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
68 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
69 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
70 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
71 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
72 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
73 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
74 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
75 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
76 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
77 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
78 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
79 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
80 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
81 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
82 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
83 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
84 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
85 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
86 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
87 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
88 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
89 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
90 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
91 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
92 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
93 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
94 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
95 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
96 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
97 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
98 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
99 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
100 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
101 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
102 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
103 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
104 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
105 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
106 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
107 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
108 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
109 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
110 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
111 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
112 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
113 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
114 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
115 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
116 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
117 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
118 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
119 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
120 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
121 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
122 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
123 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
124 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
125 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
126 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
127 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
128 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
129 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
130 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
131 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
132 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
133 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
134 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
135 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
136 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
137 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
138 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
139 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
140 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
141 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
142 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
143 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
144 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
145 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
146 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
147 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
148 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
149 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
150 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
151 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
152 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
153 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
154 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
155 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
156 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
157 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
158 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
159 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
160 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
161 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
162 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
163 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
164 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
165 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
166 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
167 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
168 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
169 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
170 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
171 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
172 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
173 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
174 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
177 static BOOL upgrade_to_version_2(void)
179 TDB_DATA kbuf, newkey, dbuf;
181 DEBUG(0,("upgrade_to_version_2: upgrading print tdb's to version 2\n"));
183 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
184 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
186 dbuf = tdb_fetch(tdb_drivers, kbuf);
188 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
189 DEBUG(0,("upgrade_to_version_2:moving form\n"));
190 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
191 DEBUG(0,("upgrade_to_version_2: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
194 if (tdb_delete(tdb_drivers, kbuf) != 0) {
195 DEBUG(0,("upgrade_to_version_2: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
200 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
201 DEBUG(0,("upgrade_to_version_2:moving printer\n"));
202 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
203 DEBUG(0,("upgrade_to_version_2: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
206 if (tdb_delete(tdb_drivers, kbuf) != 0) {
207 DEBUG(0,("upgrade_to_version_2: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
212 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
213 DEBUG(0,("upgrade_to_version_2:moving secdesc\n"));
214 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
215 DEBUG(0,("upgrade_to_version_2: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
218 if (tdb_delete(tdb_drivers, kbuf) != 0) {
219 DEBUG(0,("upgrade_to_version_2: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
224 SAFE_FREE(dbuf.dptr);
230 /****************************************************************************
231 open the NT printing tdb
232 ****************************************************************************/
233 BOOL nt_printing_init(void)
235 static pid_t local_pid;
236 char *vstring = "INFO/version";
238 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
241 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
243 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
244 lock_path("ntdrivers.tdb"), strerror(errno) ));
248 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
250 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
251 lock_path("ntprinters.tdb"), strerror(errno) ));
255 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
257 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
258 lock_path("ntforms.tdb"), strerror(errno) ));
262 local_pid = sys_getpid();
264 /* handle a Samba upgrade */
265 tdb_lock_bystring(tdb_drivers, vstring);
266 if (tdb_fetch_int(tdb_drivers, vstring) != NTDRIVERS_DATABASE_VERSION) {
268 if (tdb_fetch_int(tdb_drivers, vstring) == NTDRIVERS_DATABASE_VERSION_1) {
269 if (!upgrade_to_version_2())
272 tdb_traverse(tdb_drivers, (tdb_traverse_func)tdb_delete, NULL);
274 tdb_store_int(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
276 tdb_unlock_bystring(tdb_drivers, vstring);
281 /****************************************************************************
282 get builtin form struct list
283 ****************************************************************************/
284 int get_builtin_ntforms(nt_forms_struct **list)
286 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
287 return sizeof(default_forms) / sizeof(default_forms[0]);
290 /****************************************************************************
291 get a builtin form struct
292 ****************************************************************************/
294 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
298 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
299 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
300 count = sizeof(default_forms) / sizeof(default_forms[0]);
301 for (i=0;i<count;i++) {
302 if (strequal(form_name,default_forms[i].name)) {
303 DEBUGADD(6,("Found builtin form %s \n", form_name));
304 memcpy(form,&default_forms[i],sizeof(*form));
312 /****************************************************************************
313 get a form struct list
314 ****************************************************************************/
315 int get_ntforms(nt_forms_struct **list)
317 TDB_DATA kbuf, newkey, dbuf;
319 nt_forms_struct form;
324 for (kbuf = tdb_firstkey(tdb_forms);
326 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
327 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
329 dbuf = tdb_fetch(tdb_forms, kbuf);
330 if (!dbuf.dptr) continue;
332 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
333 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
334 &i, &form.flag, &form.width, &form.length, &form.left,
335 &form.top, &form.right, &form.bottom);
336 SAFE_FREE(dbuf.dptr);
337 if (ret != dbuf.dsize) continue;
339 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
341 DEBUG(0,("get_ntforms: Realloc fail.\n"));
353 /****************************************************************************
354 write a form struct list
355 ****************************************************************************/
356 int write_ntforms(nt_forms_struct **list, int number)
363 for (i=0;i<number;i++) {
364 /* save index, so list is rebuilt in correct order */
365 len = tdb_pack(buf, sizeof(buf), "dddddddd",
366 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
367 (*list)[i].left, (*list)[i].top, (*list)[i].right,
369 if (len > sizeof(buf)) break;
370 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
371 kbuf.dsize = strlen(key)+1;
375 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
381 /****************************************************************************
382 add a form struct at the end of the list
383 ****************************************************************************/
384 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
392 * NT tries to add forms even when
393 * they are already in the base
394 * only update the values if already present
399 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
400 for (n=0; n<*count; n++) {
401 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
402 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
409 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
410 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
414 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
418 (*list)[n].flag=form->flags;
419 (*list)[n].width=form->size_x;
420 (*list)[n].length=form->size_y;
421 (*list)[n].left=form->left;
422 (*list)[n].top=form->top;
423 (*list)[n].right=form->right;
424 (*list)[n].bottom=form->bottom;
429 /****************************************************************************
430 delete a named form struct
431 ****************************************************************************/
432 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
441 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
443 for (n=0; n<*count; n++) {
444 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
445 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
451 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
452 *ret = WERR_INVALID_PARAM;
456 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
457 kbuf.dsize = strlen(key)+1;
459 if (tdb_delete(tdb_forms, kbuf) != 0) {
467 /****************************************************************************
469 ****************************************************************************/
470 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
474 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
476 DEBUG(106, ("[%s]\n", form_name));
477 for (n=0; n<count; n++)
479 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
480 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
484 if (n==count) return;
486 (*list)[n].flag=form->flags;
487 (*list)[n].width=form->size_x;
488 (*list)[n].length=form->size_y;
489 (*list)[n].left=form->left;
490 (*list)[n].top=form->top;
491 (*list)[n].right=form->right;
492 (*list)[n].bottom=form->bottom;
495 /****************************************************************************
496 get the nt drivers list
498 traverse the database and look-up the matching names
499 ****************************************************************************/
500 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
506 TDB_DATA kbuf, newkey;
508 get_short_archi(short_archi, architecture);
509 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
511 for (kbuf = tdb_firstkey(tdb_drivers);
513 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
514 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
516 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
517 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
522 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
529 /****************************************************************************
530 function to do the mapping between the long architecture name and
532 ****************************************************************************/
533 BOOL get_short_archi(char *short_archi, char *long_archi)
540 struct table archi_table[]=
542 {"Windows 4.0", "WIN40" },
543 {"Windows NT x86", "W32X86" },
544 {"Windows NT R4000", "W32MIPS" },
545 {"Windows NT Alpha_AXP", "W32ALPHA" },
546 {"Windows NT PowerPC", "W32PPC" },
552 DEBUG(107,("Getting architecture dependant directory\n"));
555 } while ( (archi_table[i].long_archi!=NULL ) &&
556 StrCaseCmp(long_archi, archi_table[i].long_archi) );
558 if (archi_table[i].long_archi==NULL) {
559 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
563 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
565 DEBUGADD(108,("index: [%d]\n", i));
566 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
567 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
572 /****************************************************************************
573 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
574 There are two case to be covered here: PE (Portable Executable) and NE (New
575 Executable) files. Both files support the same INFO structure, but PE files
576 store the signature in unicode, and NE files store it as !unicode.
577 ****************************************************************************/
578 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
585 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
586 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
587 fname, PE_HEADER_SIZE));
591 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
592 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
593 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
595 goto no_version_info;
598 /* Is this really a DOS header? */
599 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
600 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
601 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
602 goto no_version_info;
605 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
606 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
607 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
609 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
610 goto no_version_info;
613 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
614 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
616 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
617 goto no_version_info;
620 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
621 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
623 int section_table_bytes;
625 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
626 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
627 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
628 /* At this point, we assume the file is in error. It still could be somthing
629 * else besides a PE file, but it unlikely at this point.
634 /* get the section table */
635 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
636 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
638 if ((buf=malloc(section_table_bytes)) == NULL) {
639 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
640 fname, section_table_bytes));
644 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
645 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
650 /* Iterate the section table looking for the resource section ".rsrc" */
651 for (i = 0; i < num_sections; i++) {
652 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
654 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
655 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
656 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
659 if ((buf=malloc(section_bytes)) == NULL) {
660 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
661 fname, section_bytes));
665 /* Seek to the start of the .rsrc section info */
666 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
667 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
672 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
673 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
678 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
679 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
680 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
681 /* Align to next long address */
682 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
684 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
685 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
686 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
688 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
689 fname, *major, *minor,
690 (*major>>16)&0xffff, *major&0xffff,
691 (*minor>>16)&0xffff, *minor&0xffff));
700 /* Version info not found, fall back to origin date/time */
701 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
705 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
706 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
707 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
708 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
709 /* At this point, we assume the file is in error. It still could be somthing
710 * else besides a NE file, but it unlikely at this point. */
714 /* Allocate a bit more space to speed up things */
716 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
717 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
718 fname, PE_HEADER_SIZE));
722 /* This is a HACK! I got tired of trying to sort through the messy
723 * 'NE' file format. If anyone wants to clean this up please have at
724 * it, but this works. 'NE' files will eventually fade away. JRR */
725 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
726 /* Cover case that should not occur in a well formed 'NE' .dll file */
727 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
729 for(i=0; i<byte_count; i++) {
730 /* Fast skip past data that can't possibly match */
731 if (buf[i] != 'V') continue;
733 /* Potential match data crosses buf boundry, move it to beginning
734 * of buf, and fill the buf with as much as it will hold. */
735 if (i>byte_count-VS_VERSION_INFO_SIZE) {
738 memcpy(buf, &buf[i], byte_count-i);
739 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
740 (byte_count-i))) < 0) {
742 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
747 byte_count = bc + (byte_count - i);
748 if (byte_count<VS_VERSION_INFO_SIZE) break;
753 /* Check that the full signature string and the magic number that
754 * follows exist (not a perfect solution, but the chances that this
755 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
756 * twice, as it is simpler to read the code. */
757 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
758 /* Compute skip alignment to next long address */
759 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
760 sizeof(VS_SIGNATURE)) & 3;
761 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
763 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
764 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
765 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
766 fname, *major, *minor,
767 (*major>>16)&0xffff, *major&0xffff,
768 (*minor>>16)&0xffff, *minor&0xffff));
775 /* Version info not found, fall back to origin date/time */
776 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
781 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
782 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
783 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
794 /****************************************************************************
795 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
796 share one or more files. During the MS installation process files are checked
797 to insure that only a newer version of a shared file is installed over an
798 older version. There are several possibilities for this comparison. If there
799 is no previous version, the new one is newer (obviously). If either file is
800 missing the version info structure, compare the creation date (on Unix use
801 the modification date). Otherwise chose the numerically larger version number.
802 ****************************************************************************/
803 static int file_version_is_newer(connection_struct *conn, fstring new_file,
806 BOOL use_version = True;
811 time_t new_create_time;
815 time_t old_create_time;
819 files_struct *fsp = NULL;
821 SMB_STRUCT_STAT stat_buf;
825 ZERO_STRUCT(stat_buf);
826 new_create_time = (time_t)0;
827 old_create_time = (time_t)0;
829 /* Get file version info (if available) for previous file (if it exists) */
830 pstrcpy(filepath, old_file);
832 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
834 fsp = open_file_shared(conn, filepath, &stat_buf,
835 SET_OPEN_MODE(DOS_OPEN_RDONLY),
836 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
837 0, 0, &access_mode, &action);
839 /* Old file not found, so by definition new file is in fact newer */
840 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
845 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
846 if (ret == -1) goto error_exit;
849 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
852 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
853 old_create_time = st.st_mtime;
854 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
857 close_file(fsp, True);
859 /* Get file version info (if available) for new file */
860 pstrcpy(filepath, new_file);
861 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
863 fsp = open_file_shared(conn, filepath, &stat_buf,
864 SET_OPEN_MODE(DOS_OPEN_RDONLY),
865 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
866 0, 0, &access_mode, &action);
868 /* New file not found, this shouldn't occur if the caller did its job */
869 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
874 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
875 if (ret == -1) goto error_exit;
878 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
881 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
882 new_create_time = st.st_mtime;
883 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
886 close_file(fsp, True);
889 /* Compare versions and choose the larger version number */
890 if (new_major > old_major ||
891 (new_major == old_major && new_minor > old_minor)) {
893 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
897 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
902 /* Compare modification time/dates and choose the newest time/date */
903 if (new_create_time > old_create_time) {
904 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
908 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
915 close_file(fsp, True);
919 /****************************************************************************
920 Determine the correct cVersion associated with an architecture and driver
921 ****************************************************************************/
922 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
923 struct current_user *user, WERROR *perr)
931 files_struct *fsp = NULL;
934 connection_struct *conn;
938 *perr = WERR_INVALID_PARAM;
940 /* If architecture is Windows 95/98/ME, the version is always 0. */
941 if (strcmp(architecture, "WIN40") == 0) {
942 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
947 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
948 /* Null password is ok - we are already an authenticated user... */
949 null_pw = data_blob(NULL, 0);
952 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
956 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
957 *perr = ntstatus_to_werror(nt_status);
961 /* We are temporarily becoming the connection user. */
962 if (!become_user(conn, conn->vuid)) {
963 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
964 *perr = WERR_ACCESS_DENIED;
968 /* Open the driver file (Portable Executable format) and determine the
969 * deriver the cversion. */
970 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
972 unix_convert(driverpath,conn,NULL,&bad_path,&st);
974 fsp = open_file_shared(conn, driverpath, &st,
975 SET_OPEN_MODE(DOS_OPEN_RDONLY),
976 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
977 0, 0, &access_mode, &action);
979 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
981 *perr = WERR_ACCESS_DENIED;
987 int ret = get_file_version(fsp, driverpath, &major, &minor);
988 if (ret == -1) goto error_exit;
991 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
996 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
997 * for more details. Version in this case is not just the version of the
998 * file, but the version in the sense of kernal mode (2) vs. user mode
999 * (3) drivers. Other bits of the version fields are the version info.
1002 cversion = major & 0x0000ffff;
1004 case 2: /* WinNT drivers */
1005 case 3: /* Win2K drivers */
1009 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1010 driverpath, cversion));
1014 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1015 driverpath, major, minor));
1018 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1019 driverpath, cversion));
1021 close_file(fsp, True);
1022 close_cnum(conn, user->vuid);
1030 close_file(fsp, True);
1032 close_cnum(conn, user->vuid);
1037 /****************************************************************************
1038 ****************************************************************************/
1039 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1040 struct current_user *user)
1042 fstring architecture;
1048 /* clean up the driver name.
1049 * we can get .\driver.dll
1050 * or worse c:\windows\system\driver.dll !
1052 /* using an intermediate string to not have overlaping memcpy()'s */
1053 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1054 fstrcpy(new_name, p+1);
1055 fstrcpy(driver->driverpath, new_name);
1058 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1059 fstrcpy(new_name, p+1);
1060 fstrcpy(driver->datafile, new_name);
1063 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1064 fstrcpy(new_name, p+1);
1065 fstrcpy(driver->configfile, new_name);
1068 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1069 fstrcpy(new_name, p+1);
1070 fstrcpy(driver->helpfile, new_name);
1073 if (driver->dependentfiles) {
1074 for (i=0; *driver->dependentfiles[i]; i++) {
1075 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1076 fstrcpy(new_name, p+1);
1077 fstrcpy(driver->dependentfiles[i], new_name);
1082 get_short_archi(architecture, driver->environment);
1084 /* jfm:7/16/2000 the client always sends the cversion=0.
1085 * The server should check which version the driver is by reading
1086 * the PE header of driver->driverpath.
1088 * For Windows 95/98 the version is 0 (so the value sent is correct)
1089 * For Windows NT (the architecture doesn't matter)
1090 * NT 3.1: cversion=0
1091 * NT 3.5/3.51: cversion=1
1095 if ((driver->cversion = get_correct_cversion( architecture,
1096 driver->driverpath, user, &err)) == -1)
1102 /****************************************************************************
1103 ****************************************************************************/
1104 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1105 struct current_user *user)
1107 fstring architecture;
1113 /* clean up the driver name.
1114 * we can get .\driver.dll
1115 * or worse c:\windows\system\driver.dll !
1117 /* using an intermediate string to not have overlaping memcpy()'s */
1118 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1119 fstrcpy(new_name, p+1);
1120 fstrcpy(driver->driverpath, new_name);
1123 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1124 fstrcpy(new_name, p+1);
1125 fstrcpy(driver->datafile, new_name);
1128 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1129 fstrcpy(new_name, p+1);
1130 fstrcpy(driver->configfile, new_name);
1133 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1134 fstrcpy(new_name, p+1);
1135 fstrcpy(driver->helpfile, new_name);
1138 if (driver->dependentfiles) {
1139 for (i=0; *driver->dependentfiles[i]; i++) {
1140 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1141 fstrcpy(new_name, p+1);
1142 fstrcpy(driver->dependentfiles[i], new_name);
1147 get_short_archi(architecture, driver->environment);
1149 /* jfm:7/16/2000 the client always sends the cversion=0.
1150 * The server should check which version the driver is by reading
1151 * the PE header of driver->driverpath.
1153 * For Windows 95/98 the version is 0 (so the value sent is correct)
1154 * For Windows NT (the architecture doesn't matter)
1155 * NT 3.1: cversion=0
1156 * NT 3.5/3.51: cversion=1
1160 if ((driver->version = get_correct_cversion(architecture,
1161 driver->driverpath, user, &err)) == -1)
1167 /****************************************************************************
1168 ****************************************************************************/
1169 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1170 uint32 level, struct current_user *user)
1175 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1176 driver=driver_abstract.info_3;
1177 return clean_up_driver_struct_level_3(driver, user);
1181 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1182 driver=driver_abstract.info_6;
1183 return clean_up_driver_struct_level_6(driver, user);
1186 return WERR_INVALID_PARAM;
1190 /****************************************************************************
1191 This function sucks and should be replaced. JRA.
1192 ****************************************************************************/
1194 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1196 dst->cversion = src->version;
1198 fstrcpy( dst->name, src->name);
1199 fstrcpy( dst->environment, src->environment);
1200 fstrcpy( dst->driverpath, src->driverpath);
1201 fstrcpy( dst->datafile, src->datafile);
1202 fstrcpy( dst->configfile, src->configfile);
1203 fstrcpy( dst->helpfile, src->helpfile);
1204 fstrcpy( dst->monitorname, src->monitorname);
1205 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1206 dst->dependentfiles = src->dependentfiles;
1209 #if 0 /* Debugging function */
1211 static char* ffmt(unsigned char *c){
1213 static char ffmt_str[17];
1215 for (i=0; i<16; i++) {
1216 if ((c[i] < ' ') || (c[i] > '~'))
1227 /****************************************************************************
1228 ****************************************************************************/
1229 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1230 struct current_user *user, WERROR *perr)
1232 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1233 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1234 fstring architecture;
1239 connection_struct *conn;
1247 driver=driver_abstract.info_3;
1248 else if (level==6) {
1249 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1250 driver = &converted_driver;
1252 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1256 get_short_archi(architecture, driver->environment);
1258 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1259 /* Null password is ok - we are already an authenticated user... */
1260 null_pw = data_blob(NULL, 0);
1261 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
1264 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1265 *perr = ntstatus_to_werror(nt_status);
1270 * Save who we are - we are temporarily becoming the connection user.
1275 if (!become_user(conn, conn->vuid)) {
1276 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1282 * make the directories version and version\driver_name
1283 * under the architecture directory.
1285 DEBUG(5,("Creating first directory\n"));
1286 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1287 mkdir_internal(conn, new_dir);
1289 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1290 * listed for this driver which has already been moved, skip it (note:
1291 * drivers may list the same file name several times. Then check if the
1292 * file already exists in archi\cversion\, if so, check that the version
1293 * info (or time stamps if version info is unavailable) is newer (or the
1294 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1295 * Otherwise, delete the file.
1297 * If a file is not moved to archi\cversion\ because of an error, all the
1298 * rest of the 'unmoved' driver files are removed from archi\. If one or
1299 * more of the driver's files was already moved to archi\cversion\, it
1300 * potentially leaves the driver in a partially updated state. Version
1301 * trauma will most likely occur if an client attempts to use any printer
1302 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1303 * done is appropriate... later JRR
1306 DEBUG(5,("Moving files now !\n"));
1308 if (driver->driverpath && strlen(driver->driverpath)) {
1309 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1310 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1311 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1313 status = rename_internals(conn, new_name, old_name, True);
1314 if (!NT_STATUS_IS_OK(status)) {
1315 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1316 new_name, old_name));
1317 *perr = ntstatus_to_werror(status);
1318 unlink_internals(conn, 0, new_name);
1323 unlink_internals(conn, 0, new_name);
1326 if (driver->datafile && strlen(driver->datafile)) {
1327 if (!strequal(driver->datafile, driver->driverpath)) {
1328 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1329 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1330 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1332 status = rename_internals(conn, new_name, old_name, True);
1333 if (!NT_STATUS_IS_OK(status)) {
1334 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1335 new_name, old_name));
1336 *perr = ntstatus_to_werror(status);
1337 unlink_internals(conn, 0, new_name);
1342 unlink_internals(conn, 0, new_name);
1346 if (driver->configfile && strlen(driver->configfile)) {
1347 if (!strequal(driver->configfile, driver->driverpath) &&
1348 !strequal(driver->configfile, driver->datafile)) {
1349 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1350 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1351 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1353 status = rename_internals(conn, new_name, old_name, True);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1356 new_name, old_name));
1357 *perr = ntstatus_to_werror(status);
1358 unlink_internals(conn, 0, new_name);
1363 unlink_internals(conn, 0, new_name);
1367 if (driver->helpfile && strlen(driver->helpfile)) {
1368 if (!strequal(driver->helpfile, driver->driverpath) &&
1369 !strequal(driver->helpfile, driver->datafile) &&
1370 !strequal(driver->helpfile, driver->configfile)) {
1371 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1372 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1373 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1375 status = rename_internals(conn, new_name, old_name, True);
1376 if (!NT_STATUS_IS_OK(status)) {
1377 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1378 new_name, old_name));
1379 *perr = ntstatus_to_werror(status);
1380 unlink_internals(conn, 0, new_name);
1385 unlink_internals(conn, 0, new_name);
1389 if (driver->dependentfiles) {
1390 for (i=0; *driver->dependentfiles[i]; i++) {
1391 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1392 !strequal(driver->dependentfiles[i], driver->datafile) &&
1393 !strequal(driver->dependentfiles[i], driver->configfile) &&
1394 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1396 for (j=0; j < i; j++) {
1397 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1402 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1403 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1404 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1406 status = rename_internals(conn, new_name, old_name, True);
1407 if (!NT_STATUS_IS_OK(status)) {
1408 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1409 new_name, old_name));
1410 *perr = ntstatus_to_werror(status);
1411 unlink_internals(conn, 0, new_name);
1416 unlink_internals(conn, 0, new_name);
1422 close_cnum(conn, user->vuid);
1425 return ver == -1 ? False : True;
1428 /****************************************************************************
1429 ****************************************************************************/
1430 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1433 fstring architecture;
1439 TDB_DATA kbuf, dbuf;
1441 get_short_archi(architecture, driver->environment);
1443 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1444 * \\server is added in the rpc server layer.
1445 * It does make sense to NOT store the server's name in the printer TDB.
1448 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1450 /* .inf files do not always list a file for each of the four standard files.
1451 * Don't prepend a path to a null filename, or client claims:
1452 * "The server on which the printer resides does not have a suitable
1453 * <printer driver name> printer driver installed. Click OK if you
1454 * wish to install the driver on your local machine."
1456 if (strlen(driver->driverpath)) {
1457 fstrcpy(temp_name, driver->driverpath);
1458 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1461 if (strlen(driver->datafile)) {
1462 fstrcpy(temp_name, driver->datafile);
1463 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1466 if (strlen(driver->configfile)) {
1467 fstrcpy(temp_name, driver->configfile);
1468 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1471 if (strlen(driver->helpfile)) {
1472 fstrcpy(temp_name, driver->helpfile);
1473 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1476 if (driver->dependentfiles) {
1477 for (i=0; *driver->dependentfiles[i]; i++) {
1478 fstrcpy(temp_name, driver->dependentfiles[i]);
1479 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1483 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1485 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1492 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1495 driver->environment,
1500 driver->monitorname,
1501 driver->defaultdatatype);
1503 if (driver->dependentfiles) {
1504 for (i=0; *driver->dependentfiles[i]; i++) {
1505 len += tdb_pack(buf+len, buflen-len, "f",
1506 driver->dependentfiles[i]);
1510 if (len != buflen) {
1513 tb = (char *)Realloc(buf, len);
1515 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1526 kbuf.dsize = strlen(key)+1;
1530 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1534 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1540 /****************************************************************************
1541 ****************************************************************************/
1542 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1544 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1547 info3.cversion = driver->version;
1548 fstrcpy(info3.name,driver->name);
1549 fstrcpy(info3.environment,driver->environment);
1550 fstrcpy(info3.driverpath,driver->driverpath);
1551 fstrcpy(info3.datafile,driver->datafile);
1552 fstrcpy(info3.configfile,driver->configfile);
1553 fstrcpy(info3.helpfile,driver->helpfile);
1554 fstrcpy(info3.monitorname,driver->monitorname);
1555 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1556 info3.dependentfiles = driver->dependentfiles;
1558 return add_a_printer_driver_3(&info3);
1562 /****************************************************************************
1563 ****************************************************************************/
1564 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1566 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1570 fstrcpy(info.name, in_prt);
1571 fstrcpy(info.defaultdatatype, "RAW");
1573 fstrcpy(info.driverpath, "");
1574 fstrcpy(info.datafile, "");
1575 fstrcpy(info.configfile, "");
1576 fstrcpy(info.helpfile, "");
1578 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1581 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1582 fstrcpy(info.dependentfiles[0], "");
1584 *info_ptr = memdup(&info, sizeof(info));
1589 /****************************************************************************
1590 ****************************************************************************/
1591 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1593 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1594 TDB_DATA kbuf, dbuf;
1595 fstring architecture;
1600 ZERO_STRUCT(driver);
1602 get_short_archi(architecture, in_arch);
1604 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1606 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1609 kbuf.dsize = strlen(key)+1;
1611 dbuf = tdb_fetch(tdb_drivers, kbuf);
1613 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1615 if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1617 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1626 driver.defaultdatatype);
1629 while (len < dbuf.dsize) {
1632 tddfs = (fstring *)Realloc(driver.dependentfiles,
1633 sizeof(fstring)*(i+2));
1634 if (tddfs == NULL) {
1635 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1638 else driver.dependentfiles = tddfs;
1640 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1641 &driver.dependentfiles[i]);
1644 if (driver.dependentfiles != NULL)
1645 fstrcpy(driver.dependentfiles[i], "");
1647 SAFE_FREE(dbuf.dptr);
1649 if (len != dbuf.dsize) {
1650 SAFE_FREE(driver.dependentfiles);
1652 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1655 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1660 /****************************************************************************
1661 ****************************************************************************/
1662 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1664 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1670 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1671 DEBUG(10,("driver key: [%s]\n", key));
1674 kbuf.dsize = strlen(key)+1;
1675 if (!tdb_exists(tdb_drivers, kbuf)) return False;
1678 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1680 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1681 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1682 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1683 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1684 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1685 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1686 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1688 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1689 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1690 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1692 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1693 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1694 pstrcat(line, info3->configfile);
1696 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1697 pstrcat(line, info3->datafile);
1699 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1700 pstrcat(line, info3->helpfile);
1702 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1703 pstrcat(line, info3->monitorname);
1705 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1708 for (i=0; info3->dependentfiles &&
1709 *info3->dependentfiles[i]; i++) {
1710 if (i) pstrcat(line, ","); /* don't end in a "," */
1711 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1712 pstrcat(line, info3->dependentfiles[i]);
1720 /****************************************************************************
1721 debugging function, dump at level 6 the struct in the logs
1722 ****************************************************************************/
1723 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1726 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1729 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1735 if (driver.info_3 == NULL)
1738 info3=driver.info_3;
1740 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1741 DEBUGADD(106,("name:[%s]\n", info3->name));
1742 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1743 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1744 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1745 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1746 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1747 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1748 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1750 for (i=0; info3->dependentfiles &&
1751 *info3->dependentfiles[i]; i++) {
1752 DEBUGADD(106,("dependentfile:[%s]\n",
1753 info3->dependentfiles[i]));
1760 DEBUGADD(1,("Level not implemented\n"));
1768 /****************************************************************************
1769 ****************************************************************************/
1770 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1774 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1776 if (!nt_devmode) return len;
1778 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1779 nt_devmode->devicename,
1780 nt_devmode->formname,
1782 nt_devmode->specversion,
1783 nt_devmode->driverversion,
1785 nt_devmode->driverextra,
1786 nt_devmode->orientation,
1787 nt_devmode->papersize,
1788 nt_devmode->paperlength,
1789 nt_devmode->paperwidth,
1792 nt_devmode->defaultsource,
1793 nt_devmode->printquality,
1796 nt_devmode->yresolution,
1797 nt_devmode->ttoption,
1798 nt_devmode->collate,
1799 nt_devmode->logpixels,
1802 nt_devmode->bitsperpel,
1803 nt_devmode->pelswidth,
1804 nt_devmode->pelsheight,
1805 nt_devmode->displayflags,
1806 nt_devmode->displayfrequency,
1807 nt_devmode->icmmethod,
1808 nt_devmode->icmintent,
1809 nt_devmode->mediatype,
1810 nt_devmode->dithertype,
1811 nt_devmode->reserved1,
1812 nt_devmode->reserved2,
1813 nt_devmode->panningwidth,
1814 nt_devmode->panningheight,
1815 nt_devmode->private);
1818 if (nt_devmode->private) {
1819 len += tdb_pack(buf+len, buflen-len, "B",
1820 nt_devmode->driverextra,
1821 nt_devmode->private);
1824 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1829 /****************************************************************************
1830 ****************************************************************************/
1831 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1835 while (param != NULL) {
1836 len += tdb_pack(buf+len, buflen-len, "pfdB",
1845 len += tdb_pack(buf+len, buflen-len, "p", param);
1851 /****************************************************************************
1852 delete a printer - this just deletes the printer info file, any open
1853 handles are not affected
1854 ****************************************************************************/
1855 uint32 del_a_printer(char *sharename)
1860 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1863 kbuf.dsize=strlen(key)+1;
1865 tdb_delete(tdb_printers, kbuf);
1869 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1870 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1871 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1872 /****************************************************************************
1873 ****************************************************************************/
1874 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1880 TDB_DATA kbuf, dbuf;
1883 * in addprinter: no servername and the printer is the name
1884 * in setprinter: servername is \\server
1885 * and printer is \\server\\printer
1887 * Samba manages only local printers.
1888 * we currently don't support things like path=\\other_server\printer
1891 if (info->servername[0]!='\0') {
1892 trim_string(info->printername, info->servername, NULL);
1893 trim_string(info->printername, "\\", NULL);
1894 info->servername[0]='\0';
1898 * JFM: one day I'll forget.
1899 * below that's info->portname because that's the SAMBA sharename
1900 * and I made NT 'thinks' it's the portname
1901 * the info->sharename is the thing you can name when you add a printer
1902 * that's the short-name when you create shared printer for 95/98
1903 * So I've made a limitation in SAMBA: you can only have 1 printer model
1904 * behind a SAMBA share.
1912 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1915 info->default_priority,
1932 info->printprocessor,
1936 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1938 len += pack_specifics(info->specific, buf+len, buflen-len);
1940 if (buflen != len) {
1943 tb = (char *)Realloc(buf, len);
1945 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1955 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1958 kbuf.dsize = strlen(key)+1;
1962 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
1965 if (!W_ERROR_IS_OK(ret))
1966 DEBUG(8, ("error updating printer to tdb on disk\n"));
1970 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1971 info->sharename, info->drivername, info->portname, len));
1977 /****************************************************************************
1978 ****************************************************************************/
1979 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1981 NT_PRINTER_PARAM *current;
1983 DEBUG(108,("add_a_specific_param\n"));
1985 (*param)->next=NULL;
1987 if (info_2->specific == NULL)
1989 info_2->specific=*param;
1993 current=info_2->specific;
1994 while (current->next != NULL) {
1995 current=current->next;
1997 current->next=*param;
2003 /****************************************************************************
2004 ****************************************************************************/
2005 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2007 NT_PRINTER_PARAM *current;
2008 NT_PRINTER_PARAM *previous;
2010 current=info_2->specific;
2013 if (current==NULL) return (False);
2015 if ( !strcmp(current->value, param->value) &&
2016 (strlen(current->value)==strlen(param->value)) ) {
2017 DEBUG(109,("deleting first value\n"));
2018 info_2->specific=current->next;
2019 SAFE_FREE(current->data);
2021 DEBUG(109,("deleted first value\n"));
2025 current=previous->next;
2027 while ( current!=NULL ) {
2028 if (!strcmp(current->value, param->value) &&
2029 strlen(current->value)==strlen(param->value) ) {
2030 DEBUG(109,("deleting current value\n"));
2031 previous->next=current->next;
2032 SAFE_FREE(current->data);
2034 DEBUG(109,("deleted current value\n"));
2038 previous=previous->next;
2039 current=current->next;
2044 /****************************************************************************
2045 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2046 ****************************************************************************/
2047 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2049 NT_PRINTER_PARAM *param = *param_ptr;
2054 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2056 SAFE_FREE(param->data);
2057 SAFE_FREE(*param_ptr);
2060 /****************************************************************************
2061 Malloc and return an NT devicemode.
2062 ****************************************************************************/
2064 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2067 * should I init this ones ???
2068 nt_devmode->devicename
2072 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2074 if (nt_devmode == NULL) {
2075 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2079 ZERO_STRUCTP(nt_devmode);
2081 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2082 fstrcpy(nt_devmode->devicename, adevice);
2084 fstrcpy(nt_devmode->formname, "Letter");
2086 nt_devmode->specversion = 0x0401;
2087 nt_devmode->driverversion = 0x0400;
2088 nt_devmode->size = 0x00DC;
2089 nt_devmode->driverextra = 0x0000;
2090 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2091 DEFAULTSOURCE | COPIES | SCALE |
2092 PAPERSIZE | ORIENTATION;
2093 nt_devmode->orientation = 1;
2094 nt_devmode->papersize = PAPER_LETTER;
2095 nt_devmode->paperlength = 0;
2096 nt_devmode->paperwidth = 0;
2097 nt_devmode->scale = 0x64;
2098 nt_devmode->copies = 1;
2099 nt_devmode->defaultsource = BIN_FORMSOURCE;
2100 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2101 nt_devmode->color = COLOR_MONOCHROME;
2102 nt_devmode->duplex = DUP_SIMPLEX;
2103 nt_devmode->yresolution = 0;
2104 nt_devmode->ttoption = TT_SUBDEV;
2105 nt_devmode->collate = COLLATE_FALSE;
2106 nt_devmode->icmmethod = 0;
2107 nt_devmode->icmintent = 0;
2108 nt_devmode->mediatype = 0;
2109 nt_devmode->dithertype = 0;
2111 /* non utilisés par un driver d'imprimante */
2112 nt_devmode->logpixels = 0;
2113 nt_devmode->bitsperpel = 0;
2114 nt_devmode->pelswidth = 0;
2115 nt_devmode->pelsheight = 0;
2116 nt_devmode->displayflags = 0;
2117 nt_devmode->displayfrequency = 0;
2118 nt_devmode->reserved1 = 0;
2119 nt_devmode->reserved2 = 0;
2120 nt_devmode->panningwidth = 0;
2121 nt_devmode->panningheight = 0;
2123 nt_devmode->private = NULL;
2127 /****************************************************************************
2128 Deepcopy an NT devicemode.
2129 ****************************************************************************/
2131 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2133 NT_DEVICEMODE *new_nt_devicemode = NULL;
2135 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2136 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2140 new_nt_devicemode->private = NULL;
2141 if (nt_devicemode->private != NULL) {
2142 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2143 SAFE_FREE(new_nt_devicemode);
2144 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2149 return new_nt_devicemode;
2152 /****************************************************************************
2153 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2154 ****************************************************************************/
2156 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2158 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2160 if(nt_devmode == NULL)
2163 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2165 SAFE_FREE(nt_devmode->private);
2166 SAFE_FREE(*devmode_ptr);
2169 /****************************************************************************
2170 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2171 ****************************************************************************/
2172 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2174 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2175 NT_PRINTER_PARAM *param_ptr;
2180 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2182 free_nt_devicemode(&info->devmode);
2184 for(param_ptr = info->specific; param_ptr; ) {
2185 NT_PRINTER_PARAM *tofree = param_ptr;
2187 param_ptr = param_ptr->next;
2188 free_nt_printer_param(&tofree);
2191 SAFE_FREE(*info_ptr);
2195 /****************************************************************************
2196 ****************************************************************************/
2197 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2201 NT_DEVICEMODE devmode;
2203 ZERO_STRUCT(devmode);
2205 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2207 if (!*nt_devmode) return len;
2209 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2213 &devmode.specversion,
2214 &devmode.driverversion,
2216 &devmode.driverextra,
2217 &devmode.orientation,
2219 &devmode.paperlength,
2220 &devmode.paperwidth,
2223 &devmode.defaultsource,
2224 &devmode.printquality,
2227 &devmode.yresolution,
2233 &devmode.bitsperpel,
2235 &devmode.pelsheight,
2236 &devmode.displayflags,
2237 &devmode.displayfrequency,
2241 &devmode.dithertype,
2244 &devmode.panningwidth,
2245 &devmode.panningheight,
2248 if (devmode.private) {
2249 /* the len in tdb_unpack is an int value and
2250 * devmode.driverextra is only a short
2252 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2253 devmode.driverextra=(uint16)extra_len;
2255 /* check to catch an invalid TDB entry so we don't segfault */
2256 if (devmode.driverextra == 0) {
2257 devmode.private = NULL;
2261 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2263 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2264 if (devmode.private)
2265 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2270 /****************************************************************************
2271 ****************************************************************************/
2272 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2275 NT_PRINTER_PARAM param, *p;
2280 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2283 len += tdb_unpack(buf+len, buflen-len, "fdB",
2289 *list = memdup(¶m, sizeof(param));
2291 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2297 static void map_to_os2_driver(fstring drivername)
2299 static BOOL initialised=False;
2300 static fstring last_from,last_to;
2301 char *mapfile = lp_os2_driver_map();
2302 char **lines = NULL;
2306 if (!strlen(drivername))
2313 *last_from = *last_to = 0;
2317 if (strequal(drivername,last_from)) {
2318 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2319 fstrcpy(drivername,last_to);
2323 lines = file_lines_load(mapfile, &numlines);
2324 if (numlines == 0) {
2325 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2329 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2331 for( i = 0; i < numlines; i++) {
2332 char *nt_name = lines[i];
2333 char *os2_name = strchr(nt_name,'=');
2340 while (isspace(*nt_name))
2343 if (!*nt_name || strchr("#;",*nt_name))
2347 int l = strlen(nt_name);
2348 while (l && isspace(nt_name[l-1])) {
2354 while (isspace(*os2_name))
2358 int l = strlen(os2_name);
2359 while (l && isspace(os2_name[l-1])) {
2365 if (strequal(nt_name,drivername)) {
2366 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2367 fstrcpy(last_from,drivername);
2368 fstrcpy(last_to,os2_name);
2369 fstrcpy(drivername,os2_name);
2370 file_lines_free(lines);
2375 file_lines_free(lines);
2378 /****************************************************************************
2379 get a default printer info 2 struct
2380 ****************************************************************************/
2381 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2383 extern pstring global_myname;
2385 NT_PRINTER_INFO_LEVEL_2 info;
2389 snum = lp_servicenumber(sharename);
2391 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2392 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2393 global_myname, sharename);
2394 fstrcpy(info.sharename, sharename);
2395 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2396 fstrcpy(info.drivername, lp_printerdriver(snum));
2398 /* by setting the driver name to an empty string, a local NT admin
2399 can now run the **local** APW to install a local printer driver
2400 for a Samba shared printer in 2.2. Without this, drivers **must** be
2401 installed on the Samba server for NT clients --jerry */
2402 #if 0 /* JERRY --do not uncomment-- */
2403 if (!*info.drivername)
2404 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2408 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2410 pstrcpy(info.comment, "");
2411 fstrcpy(info.printprocessor, "winprint");
2412 fstrcpy(info.datatype, "RAW");
2414 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2415 | PRINTER_ATTRIBUTE_LOCAL \
2416 | PRINTER_ATTRIBUTE_RAW_ONLY \
2417 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2419 info.starttime = 0; /* Minutes since 12:00am GMT */
2420 info.untiltime = 0; /* Minutes since 12:00am GMT */
2422 info.default_priority = 1;
2423 info.setuptime = (uint32)time(NULL) - 86400; /* minus 1 day */
2426 * I changed this as I think it is better to have a generic
2427 * DEVMODE than to crash Win2k explorer.exe --jerry
2428 * See the HP Deskjet 990c Win2k drivers for an example.
2431 #if 0 /* JRA - NO NOT CHANGE ! */
2432 info.devmode = NULL;
2435 * We should not return a default devicemode, as this causes
2436 * Win2K to not send the correct one on PCL drivers. It needs to
2437 * see a null devicemode so it can then overwrite the devicemode
2438 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2440 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2444 /* This will get the current RPC talloc context, but we should be
2445 passing this as a parameter... fixme... JRA ! */
2447 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2450 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2452 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2461 free_nt_devicemode(&info.devmode);
2462 return WERR_ACCESS_DENIED;
2465 /****************************************************************************
2466 ****************************************************************************/
2467 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2470 NT_PRINTER_INFO_LEVEL_2 info;
2472 TDB_DATA kbuf, dbuf;
2473 fstring printername;
2477 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2480 kbuf.dsize = strlen(key)+1;
2482 dbuf = tdb_fetch(tdb_printers, kbuf);
2484 return get_a_printer_2_default(info_ptr, sharename);
2486 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2489 &info.default_priority,
2506 info.printprocessor,
2510 /* Samba has to have shared raw drivers. */
2511 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2513 /* Restore the stripped strings. */
2514 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
2515 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
2517 fstrcpy(info.printername, printername);
2519 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2522 * Some client drivers freak out if there is a NULL devmode
2523 * (probably the driver is not checking before accessing
2524 * the devmode pointer) --jerry
2528 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2530 info.devmode = construct_nt_devicemode(printername);
2533 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2535 /* This will get the current RPC talloc context, but we should be
2536 passing this as a parameter... fixme... JRA ! */
2538 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2540 /* Fix for OS/2 drivers. */
2542 if (get_remote_arch() == RA_OS2)
2543 map_to_os2_driver(info.drivername);
2545 SAFE_FREE(dbuf.dptr);
2546 *info_ptr=memdup(&info, sizeof(info));
2548 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2549 sharename, info.printername, info.drivername));
2554 /****************************************************************************
2555 debugging function, dump at level 6 the struct in the logs
2556 ****************************************************************************/
2557 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2560 NT_PRINTER_INFO_LEVEL_2 *info2;
2562 DEBUG(106,("Dumping printer at level [%d]\n", level));
2568 if (printer.info_2 == NULL)
2572 info2=printer.info_2;
2574 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2575 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2576 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2577 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2578 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2579 DEBUGADD(106,("status:[%s]\n", werror_str(info2->status)));
2580 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2581 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2582 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2583 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2584 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2586 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2587 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2588 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2589 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2590 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2591 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2592 DEBUGADD(106,("location:[%s]\n", info2->location));
2593 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2594 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2595 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2596 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2602 DEBUGADD(1,("Level not implemented\n"));
2610 /****************************************************************************
2611 Get the parameters we can substitute in an NT print job.
2612 ****************************************************************************/
2614 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2616 NT_PRINTER_INFO_LEVEL *printer = NULL;
2618 **printername = **sharename = **portname = '\0';
2620 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2623 fstrcpy(*printername, printer->info_2->printername);
2624 fstrcpy(*sharename, printer->info_2->sharename);
2625 fstrcpy(*portname, printer->info_2->portname);
2627 free_a_printer(&printer, 2);
2631 * The function below are the high level ones.
2632 * only those ones must be called from the spoolss code.
2636 /****************************************************************************
2637 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2638 ****************************************************************************/
2640 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2644 dump_a_printer(printer, level);
2651 * Update the changestamp. Emperical tests show that the
2652 * ChangeID is always updated,but c_setprinter is only
2653 * incremented on a SetPrinter() call.
2656 time_t time_unix = time(NULL);
2658 /* ChangeID **must** be increasing over the lifetime
2659 of client's spoolss service in order for the
2660 client's cache to show updates */
2662 printer.info_2->changeid = time_unix * 100;
2665 * Because one day someone will ask:
2666 * NT->NT An admin connection to a remote
2667 * printer show changes imeediately in
2668 * the properities dialog
2670 * A non-admin connection will only show the
2671 * changes after viewing the properites page
2672 * 2 times. Seems to be related to a
2673 * race condition in the client between the spooler
2674 * updating the local cache and the Explorer.exe GUI
2675 * actually displaying the properties.
2677 * This is fixed in Win2k. admin/non-admin
2678 * connections both display changes immediately.
2683 result=update_a_printer_2(printer.info_2);
2687 result=WERR_UNKNOWN_LEVEL;
2694 /****************************************************************************
2695 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2696 We split this out from mod_a_printer as it updates the id's and timestamps.
2697 ****************************************************************************/
2699 WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2703 dump_a_printer(printer, level);
2710 * Update the changestamp. See comments in mod_a_printer()
2714 time_t time_unix = time(NULL);
2716 printer.info_2->changeid = time_unix * 100;
2717 printer.info_2->c_setprinter++;
2719 result=update_a_printer_2(printer.info_2);
2723 result=WERR_UNKNOWN_LEVEL;
2730 /****************************************************************************
2731 Initialize printer devmode & data with previously saved driver init values.
2732 ****************************************************************************/
2733 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2737 TDB_DATA kbuf, dbuf;
2738 NT_PRINTER_PARAM *current;
2739 NT_PRINTER_INFO_LEVEL_2 info;
2743 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2746 kbuf.dsize = strlen(key)+1;
2748 dbuf = tdb_fetch(tdb_drivers, kbuf);
2753 * Get the saved DEVMODE..
2755 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2758 * The saved DEVMODE contains the devicename from the printer used during
2759 * the initialization save. Change it to reflect the new printer.
2761 ZERO_STRUCT(info.devmode->devicename);
2762 fstrcpy(info.devmode->devicename, info_ptr->printername);
2765 * Bind the saved DEVMODE to the new the printer.
2767 free_nt_devicemode(&info_ptr->devmode);
2768 info_ptr->devmode = info.devmode;
2770 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2771 info_ptr->printername, info_ptr->drivername));
2774 * There should not be any printer data 'specifics' already set during the
2775 * add printer operation, if there are delete them.
2777 while ( (current=info_ptr->specific) != NULL ) {
2778 info_ptr->specific=current->next;
2779 SAFE_FREE(current->data);
2784 * Add the printer data 'specifics' to the new printer
2786 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2788 SAFE_FREE(dbuf.dptr);
2793 /****************************************************************************
2794 Initialize printer devmode & data with previously saved driver init values.
2795 When a printer is created using AddPrinter, the drivername bound to the
2796 printer is used to lookup previously saved driver initialization info, which
2797 is bound to the new printer.
2798 ****************************************************************************/
2800 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2808 result=set_driver_init_2(printer->info_2);
2819 /****************************************************************************
2820 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2821 in the tdb. Note: this is different from the driver entry and the printer
2822 entry. There should be a single driver init entry for each driver regardless
2823 of whether it was installed from NT or 2K. Technically, they should be
2824 different, but they work out to the same struct.
2825 ****************************************************************************/
2826 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2830 int buflen, len, ret;
2831 TDB_DATA kbuf, dbuf;
2838 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2840 len += pack_specifics(info->specific, buf+len, buflen-len);
2842 if (buflen != len) {
2845 tb = (char *)Realloc(buf, len);
2847 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2856 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2859 kbuf.dsize = strlen(key)+1;
2863 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2867 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2871 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2872 info->sharename, info->drivername));
2877 /****************************************************************************
2878 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2879 ****************************************************************************/
2881 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2885 dump_a_printer(printer, level);
2891 result=update_driver_init_2(printer.info_2);
2902 /****************************************************************************
2903 Convert the printer data value, a REG_BINARY array, into an initialization
2904 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2905 got to keep the endians happy :).
2906 ****************************************************************************/
2908 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2910 BOOL result = False;
2914 ZERO_STRUCT(devmode);
2916 prs_init(&ps, 0, ctx, UNMARSHALL);
2917 ps.data_p = (char *)param->data;
2918 ps.buffer_size = param->data_len;
2920 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2921 result = convert_devicemode("", &devmode, &nt_devmode);
2923 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2928 /****************************************************************************
2929 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2931 1. Use the driver's config DLL to this UNC printername and:
2932 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2933 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2934 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2936 The last step triggers saving the "driver initialization" information for
2937 this printer into the tdb. Later, new printers that use this driver will
2938 have this initialization information bound to them. This simulates the
2939 driver initialization, as if it had run on the Samba server (as it would
2942 The Win32 client side code requirement sucks! But until we can run arbitrary
2943 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2945 It would have been easier to use SetPrinter because all the UNMARSHALLING of
2946 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2947 about it and you will realize why. JRR 010720
2948 ****************************************************************************/
2950 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2952 WERROR status = WERR_OK;
2953 TALLOC_CTX *ctx = NULL;
2954 NT_DEVICEMODE *nt_devmode = NULL;
2955 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2958 * Set devmode on printer info, so entire printer initialization can be
2961 if ((ctx = talloc_init()) == NULL)
2964 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2965 status = WERR_NOMEM;
2969 ZERO_STRUCTP(nt_devmode);
2972 * The DEVMODE is held in the 'data' component of the param in raw binary.
2973 * Convert it to to a devmode structure
2975 if (!convert_driver_init(param, ctx, nt_devmode)) {
2976 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
2977 status = WERR_INVALID_PARAM;
2982 * Pack up and add (or update) the DEVMODE and any current printer data to
2983 * a 'driver init' element in the tdb
2986 printer->info_2->devmode = nt_devmode;
2987 if (update_driver_init(*printer, 2)!=0) {
2988 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
2989 status = WERR_NOMEM;
2994 * If driver initialization info was successfully saved, set the current
2995 * printer to match it. This allows initialization of the current printer
2996 * as well as the driver.
2998 status = mod_a_printer(*printer, 2);
2999 if (!W_ERROR_IS_OK(status)) {
3000 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3001 printer->info_2->printername));
3005 talloc_destroy(ctx);
3007 SAFE_FREE(nt_devmode->private);
3008 SAFE_FREE(nt_devmode);
3009 printer->info_2->devmode = tmp_devmode;
3014 /****************************************************************************
3015 Update the driver init info (DEVMODE and specifics) for a printer
3016 ****************************************************************************/
3018 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3020 WERROR status = WERR_OK;
3026 status=save_driver_init_2(printer, param);
3030 status=WERR_UNKNOWN_LEVEL;
3037 /****************************************************************************
3038 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3039 ****************************************************************************/
3041 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3044 NT_PRINTER_INFO_LEVEL *printer = NULL;
3048 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3054 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3055 DEBUG(0,("get_a_printer: malloc fail.\n"));
3058 ZERO_STRUCTP(printer);
3059 result=get_a_printer_2(&printer->info_2, sharename);
3060 if (W_ERROR_IS_OK(result)) {
3061 dump_a_printer(*printer, level);
3062 *pp_printer = printer;
3069 result=WERR_UNKNOWN_LEVEL;
3073 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, werror_str(result)));
3078 /****************************************************************************
3079 Deletes a NT_PRINTER_INFO_LEVEL struct.
3080 ****************************************************************************/
3082 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3085 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3087 DEBUG(104,("freeing a printer at level [%d]\n", level));
3089 if (printer == NULL)
3096 if (printer->info_2 != NULL)
3098 free_nt_printer_info_level_2(&printer->info_2);
3112 SAFE_FREE(*pp_printer);
3116 /****************************************************************************
3117 ****************************************************************************/
3118 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3121 DEBUG(104,("adding a printer at level [%d]\n", level));
3122 dump_a_printer_driver(driver, level);
3128 result=add_a_printer_driver_3(driver.info_3);
3134 result=add_a_printer_driver_6(driver.info_6);
3144 /****************************************************************************
3145 ****************************************************************************/
3146 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3147 fstring printername, fstring architecture, uint32 version)
3155 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3163 if (W_ERROR_IS_OK(result))
3164 dump_a_printer_driver(*driver, level);
3168 /****************************************************************************
3169 ****************************************************************************/
3170 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3178 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3179 if (driver.info_3 != NULL)
3181 info3=driver.info_3;
3182 SAFE_FREE(info3->dependentfiles);
3183 ZERO_STRUCTP(info3);
3195 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3196 if (driver.info_6 != NULL)
3198 info6=driver.info_6;
3199 SAFE_FREE(info6->dependentfiles);
3200 SAFE_FREE(info6->previousnames);
3201 ZERO_STRUCTP(info6);
3219 /****************************************************************************
3220 Determine whether or not a particular driver is currently assigned
3222 ****************************************************************************/
3223 BOOL printer_driver_in_use (char *arch, char *driver)
3225 TDB_DATA kbuf, newkey, dbuf;
3226 NT_PRINTER_INFO_LEVEL_2 info;
3230 if (!nt_printing_init())
3233 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3235 /* loop through the printers.tdb and check for the drivername */
3236 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3237 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3240 dbuf = tdb_fetch(tdb_printers, kbuf);
3244 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3247 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3250 &info.default_priority,
3267 info.printprocessor,
3271 SAFE_FREE(dbuf.dptr);
3274 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3279 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3280 info.printername, info.drivername));
3282 if (strcmp(info.drivername, driver) == 0)
3284 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3285 info.printername, driver));
3289 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3293 /* report that the driver is in use by default */
3297 /****************************************************************************
3298 Remove a printer driver from the TDB. This assumes that the the driver was
3299 previously looked up.
3300 ***************************************************************************/
3301 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3308 get_short_archi(arch, i->environment);
3309 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3310 arch, i->cversion, i->name);
3311 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3314 kbuf.dsize=strlen(key)+1;
3316 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3317 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3318 return WERR_ACCESS_DENIED;
3321 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3326 /****************************************************************************
3327 ****************************************************************************/
3328 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3329 fstring value, uint8 **data, uint32 *type, uint32 *len)
3331 /* right now that's enough ! */
3332 NT_PRINTER_PARAM *param;
3335 param=printer.info_2->specific;
3337 while (param != NULL && i < param_index) {
3345 /* exited because it exist */
3347 StrnCpy(value, param->value, sizeof(fstring)-1);
3348 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3351 ZERO_STRUCTP(*data);
3352 memcpy(*data, param->data, param->data_len);
3353 *len=param->data_len;
3357 /****************************************************************************
3358 ****************************************************************************/
3359 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3360 fstring value, uint8 **data, uint32 *type, uint32 *len)
3362 /* right now that's enough ! */
3363 NT_PRINTER_PARAM *param;
3365 DEBUG(10, ("get_specific_param\n"));
3367 param=printer.info_2->specific;
3369 while (param != NULL)
3371 #if 1 /* JRA - I think this should be case insensitive.... */
3372 if ( strequal(value, param->value)
3374 if ( !strcmp(value, param->value)
3376 && strlen(value)==strlen(param->value))
3384 DEBUGADD(10, ("get_specific_param: found one param\n"));
3385 /* exited because it exist */
3388 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3391 memcpy(*data, param->data, param->data_len);
3392 *len=param->data_len;
3394 DEBUGADD(10, ("get_specific_param: exit true\n"));
3397 DEBUGADD(10, ("get_specific_param: exit false\n"));
3401 /****************************************************************************
3402 Store a security desc for a printer.
3403 ****************************************************************************/
3405 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3407 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3408 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3410 TALLOC_CTX *mem_ctx = NULL;
3414 mem_ctx = talloc_init();
3415 if (mem_ctx == NULL)
3418 /* The old owner and group sids of the security descriptor are not
3419 present when new ACEs are added or removed by changing printer
3420 permissions through NT. If they are NULL in the new security
3421 descriptor then copy them over from the old one. */
3423 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3424 DOM_SID *owner_sid, *group_sid;
3425 SEC_ACL *dacl, *sacl;
3426 SEC_DESC *psd = NULL;
3429 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3431 /* Pick out correct owner and group sids */
3433 owner_sid = secdesc_ctr->sec->owner_sid ?
3434 secdesc_ctr->sec->owner_sid :
3435 old_secdesc_ctr->sec->owner_sid;
3437 group_sid = secdesc_ctr->sec->grp_sid ?
3438 secdesc_ctr->sec->grp_sid :
3439 old_secdesc_ctr->sec->grp_sid;
3441 dacl = secdesc_ctr->sec->dacl ?
3442 secdesc_ctr->sec->dacl :
3443 old_secdesc_ctr->sec->dacl;
3445 sacl = secdesc_ctr->sec->sacl ?
3446 secdesc_ctr->sec->sacl :
3447 old_secdesc_ctr->sec->sacl;
3449 /* Make a deep copy of the security descriptor */
3451 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3452 owner_sid, group_sid,
3457 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3460 if (!new_secdesc_ctr) {
3461 new_secdesc_ctr = secdesc_ctr;
3464 /* Store the security descriptor in a tdb */
3466 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3467 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3469 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3471 status = WERR_BADFUNC;
3475 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3477 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3480 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3481 status = WERR_BADFUNC;
3484 /* Free malloc'ed memory */
3490 talloc_destroy(mem_ctx);
3494 /****************************************************************************
3495 Construct a default security descriptor buffer for a printer.
3496 ****************************************************************************/
3498 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3502 SEC_ACL *psa = NULL;
3503 SEC_DESC_BUF *sdb = NULL;
3504 SEC_DESC *psd = NULL;
3507 enum SID_NAME_USE name_type;
3509 /* Create an ACE where Everyone is allowed to print */
3511 init_sec_access(&sa, PRINTER_ACE_PRINT);
3512 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3513 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3515 /* Make the security descriptor owned by the Administrators group
3516 on the PDC of the domain. */
3518 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
3519 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3523 /* Backup plan - make printer owned by admins or root.
3524 This should emulate a lanman printer as security
3525 settings can't be changed. */
3527 sid_peek_rid(&owner_sid, &owner_rid);
3529 if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
3530 owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
3531 owner_rid != DOMAIN_USER_RID_ADMIN &&
3532 !lookup_name("root", &owner_sid, &name_type)) {
3533 sid_copy(&owner_sid, &global_sid_World);
3537 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3538 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3539 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3540 SEC_ACE_FLAG_INHERIT_ONLY);
3542 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3543 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3544 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3546 /* The ACL revision number in rpc_secdesc.h differs from the one
3547 created by NT when setting ACE entries in printer
3548 descriptors. NT4 complains about the property being edited by a
3551 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3552 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3554 NULL, psa, &sd_size);
3558 DEBUG(0,("construct_default_printer_sdb: Failed to make SEC_DESC.\n"));
3562 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3564 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3565 (unsigned int)sd_size));
3570 /****************************************************************************
3571 Get a security desc for a printer.
3572 ****************************************************************************/
3574 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3580 if ((temp = strchr(printername + 2, '\\'))) {
3581 printername = temp + 1;
3584 /* Fetch security descriptor from tdb */
3586 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3588 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3589 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3591 DEBUG(4,("using default secdesc for %s\n", printername));
3593 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3597 /* Save default security descriptor for later */
3599 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
3600 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
3602 if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
3603 tdb_prs_store(tdb_printers, key, &ps);
3610 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3611 this security descriptor has been created when winbindd was
3612 down. Take ownership of security descriptor. */
3614 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3616 enum SID_NAME_USE name_type;
3618 /* Change sd owner to workgroup administrator */
3620 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
3622 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3623 SEC_DESC *psd = NULL;
3628 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3630 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3632 (*secdesc_ctr)->sec->grp_sid,
3633 (*secdesc_ctr)->sec->sacl,
3634 (*secdesc_ctr)->sec->dacl,
3637 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3639 /* Swap with other one */
3641 *secdesc_ctr = new_secdesc_ctr;
3645 nt_printing_setsec(printername, *secdesc_ctr);
3649 if (DEBUGLEVEL >= 10) {
3650 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3653 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3654 printername, the_acl->num_aces));
3656 for (i = 0; i < the_acl->num_aces; i++) {
3659 sid_to_string(sid_str, &the_acl->ace[i].trustee);
3661 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3662 the_acl->ace[i].type, the_acl->ace[i].flags,
3663 the_acl->ace[i].info.mask));
3673 1: level not implemented
3674 2: file doesn't exist
3675 3: can't allocate memory
3676 4: can't free memory
3677 5: non existant struct
3681 A printer and a printer driver are 2 different things.
3682 NT manages them separatelly, Samba does the same.
3683 Why ? Simply because it's easier and it makes sense !
3685 Now explanation: You have 3 printers behind your samba server,
3686 2 of them are the same make and model (laser A and B). But laser B
3687 has an 3000 sheet feeder and laser A doesn't such an option.
3688 Your third printer is an old dot-matrix model for the accounting :-).
3690 If the /usr/local/samba/lib directory (default dir), you will have
3691 5 files to describe all of this.
3693 3 files for the printers (1 by printer):
3696 NTprinter_accounting
3697 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3698 NTdriver_printer model X
3699 NTdriver_printer model Y
3701 jfm: I should use this comment for the text file to explain
3702 same thing for the forms BTW.
3703 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3707 /* Convert generic access rights to printer object specific access rights.
3708 It turns out that NT4 security descriptors use generic access rights and
3709 NT5 the object specific ones. */
3711 void map_printer_permissions(SEC_DESC *sd)
3715 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3716 se_map_generic(&sd->dacl->ace[i].info.mask,
3717 &printer_generic_mapping);
3721 /****************************************************************************
3722 Check a user has permissions to perform the given operation. We use the
3723 permission constants defined in include/rpc_spoolss.h to check the various
3724 actions we perform when checking printer access.
3726 PRINTER_ACCESS_ADMINISTER:
3727 print_queue_pause, print_queue_resume, update_printer_sec,
3728 update_printer, spoolss_addprinterex_level_2,
3729 _spoolss_setprinterdata
3734 JOB_ACCESS_ADMINISTER:
3735 print_job_delete, print_job_pause, print_job_resume,
3738 ****************************************************************************/
3739 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3741 SEC_DESC_BUF *secdesc = NULL;
3742 uint32 access_granted;
3746 TALLOC_CTX *mem_ctx = NULL;
3747 extern struct current_user current_user;
3749 /* If user is NULL then use the current_user structure */
3752 user = ¤t_user;
3754 /* Always allow root or printer admins to do anything */
3756 if (user->uid == 0 ||
3757 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3761 /* Get printer name */
3763 pname = PRINTERNAME(snum);
3765 if (!pname || !*pname) {
3770 /* Get printer security descriptor */
3772 if(!(mem_ctx = talloc_init())) {
3777 nt_printing_getsec(mem_ctx, pname, &secdesc);
3779 if (access_type == JOB_ACCESS_ADMINISTER) {
3780 SEC_DESC_BUF *parent_secdesc = secdesc;
3782 /* Create a child security descriptor to check permissions
3783 against. This is because print jobs are child objects
3784 objects of a printer. */
3786 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3788 /* Now this is the bit that really confuses me. The access
3789 type needs to be changed from JOB_ACCESS_ADMINISTER to
3790 PRINTER_ACCESS_ADMINISTER for this to work. Something
3791 to do with the child (job) object becoming like a
3794 access_type = PRINTER_ACCESS_ADMINISTER;
3799 map_printer_permissions(secdesc->sec);
3801 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
3802 &access_granted, &status);
3804 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3806 talloc_destroy(mem_ctx);
3814 /****************************************************************************
3815 Check the time parameters allow a print operation.
3816 *****************************************************************************/
3818 BOOL print_time_access_check(int snum)
3820 NT_PRINTER_INFO_LEVEL *printer = NULL;
3822 time_t now = time(NULL);
3826 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3829 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3833 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3835 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3838 free_a_printer(&printer, 2);
3846 /****************************************************************************
3847 Attempt to write a default device.
3848 *****************************************************************************/
3850 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3852 NT_PRINTER_INFO_LEVEL *printer = NULL;
3856 * Don't bother if no default devicemode was sent.
3859 if (printer_default->devmode_cont.devmode == NULL)
3862 result = get_a_printer(&printer, 2, lp_servicename(snum));
3863 if (!W_ERROR_IS_OK(result)) return result;
3866 * Just ignore it if we already have a devmode.
3869 if (printer->info_2->devmode != NULL)
3873 * We don't have a devicemode and we're trying to write
3874 * one. Check we have the access needed.
3876 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3878 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3879 PRINTER_ACCESS_ADMINISTER) {
3880 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3881 result = WERR_ACCESS_DENIED;
3885 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3886 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3887 lp_servicename(snum) ));
3888 result = WERR_ACCESS_DENIED;
3889 /*result = NT_STATUS_NO_PROBLEMO;*/
3893 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3896 * Convert the on the wire devicemode format to the internal one.
3899 if (!convert_devicemode(printer->info_2->printername,
3900 printer_default->devmode_cont.devmode,
3901 &printer->info_2->devmode)) {
3902 result = WERR_NOMEM;
3907 * Finally write back to the tdb.
3910 result = add_a_printer(*printer, 2);
3914 free_a_printer(&printer, 2);