r2176: syncing necessary changes for 3.0.7
[Samba.git] / source / printing / nt_printing.c
blob7850924aacb899fb02f57e8225bfd65bb67568e1
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2003.
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.
23 #include "includes.h"
25 extern DOM_SID global_sid_World;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping = {
47 PRINTER_READ,
48 PRINTER_WRITE,
49 PRINTER_EXECUTE,
50 PRINTER_ALL_ACCESS
53 STANDARD_MAPPING printer_std_mapping = {
54 PRINTER_READ,
55 PRINTER_WRITE,
56 PRINTER_EXECUTE,
57 PRINTER_ALL_ACCESS
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping = {
63 SERVER_READ,
64 SERVER_WRITE,
65 SERVER_EXECUTE,
66 SERVER_ALL_ACCESS
69 STANDARD_MAPPING printserver_std_mapping = {
70 SERVER_READ,
71 SERVER_WRITE,
72 SERVER_EXECUTE,
73 SERVER_ALL_ACCESS
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 struct table_node {
202 const char *long_archi;
203 const char *short_archi;
204 int version;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
213 static const struct table_node archi_table[]= {
215 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
216 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
217 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
218 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
219 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
220 {NULL, "", -1 }
223 static BOOL upgrade_to_version_3(void)
225 TDB_DATA kbuf, newkey, dbuf;
227 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
229 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
230 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
232 dbuf = tdb_fetch(tdb_drivers, kbuf);
234 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
235 DEBUG(0,("upgrade_to_version_3:moving form\n"));
236 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
237 SAFE_FREE(dbuf.dptr);
238 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
239 return False;
241 if (tdb_delete(tdb_drivers, kbuf) != 0) {
242 SAFE_FREE(dbuf.dptr);
243 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
244 return False;
248 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
249 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
251 SAFE_FREE(dbuf.dptr);
252 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
253 return False;
255 if (tdb_delete(tdb_drivers, kbuf) != 0) {
256 SAFE_FREE(dbuf.dptr);
257 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
258 return False;
262 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
263 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
265 SAFE_FREE(dbuf.dptr);
266 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
267 return False;
269 if (tdb_delete(tdb_drivers, kbuf) != 0) {
270 SAFE_FREE(dbuf.dptr);
271 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
272 return False;
276 SAFE_FREE(dbuf.dptr);
279 return True;
282 /****************************************************************************
283 Open the NT printing tdbs. Done once before fork().
284 ****************************************************************************/
286 BOOL nt_printing_init(void)
288 static pid_t local_pid;
289 const char *vstring = "INFO/version";
291 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
292 return True;
294 if (tdb_drivers)
295 tdb_close(tdb_drivers);
296 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
297 if (!tdb_drivers) {
298 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299 lock_path("ntdrivers.tdb"), strerror(errno) ));
300 return False;
303 if (tdb_printers)
304 tdb_close(tdb_printers);
305 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
306 if (!tdb_printers) {
307 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308 lock_path("ntprinters.tdb"), strerror(errno) ));
309 return False;
312 if (tdb_forms)
313 tdb_close(tdb_forms);
314 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
315 if (!tdb_forms) {
316 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317 lock_path("ntforms.tdb"), strerror(errno) ));
318 return False;
321 local_pid = sys_getpid();
323 /* handle a Samba upgrade */
324 tdb_lock_bystring(tdb_drivers, vstring, 0);
326 int32 vers_id;
328 /* Cope with byte-reversed older versions of the db. */
329 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
330 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
331 /* Written on a bigendian machine with old fetch_int code. Save as le. */
332 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
333 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
334 vers_id = NTDRIVERS_DATABASE_VERSION;
337 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
339 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
340 if (!upgrade_to_version_3())
341 return False;
342 } else
343 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
345 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
348 tdb_unlock_bystring(tdb_drivers, vstring);
350 update_c_setprinter(True);
353 * register callback to handle updating printers as new
354 * drivers are installed
357 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
360 * register callback to handle updating printer data
361 * when a driver is initialized
364 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
367 * register callback to handle invalidating the printer cache
368 * between smbd processes.
371 message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
373 /* of course, none of the message callbacks matter if you don't
374 tell messages.c that you interested in receiving PRINT_GENERAL
375 msgs. This is done in claim_connection() */
378 return True;
381 /*******************************************************************
382 Function to allow filename parsing "the old way".
383 ********************************************************************/
385 static BOOL driver_unix_convert(char *name,connection_struct *conn,
386 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
388 unix_format(name);
389 unix_clean_name(name);
390 trim_string(name,"/","/");
391 return unix_convert(name, conn, saved_last_component, bad_path, pst);
394 /*******************************************************************
395 tdb traversal function for counting printers.
396 ********************************************************************/
398 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
399 TDB_DATA data, void *context)
401 int *printer_count = (int*)context;
403 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
404 (*printer_count)++;
405 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
408 return 0;
411 /*******************************************************************
412 Update the spooler global c_setprinter. This variable is initialized
413 when the parent smbd starts with the number of existing printers. It
414 is monotonically increased by the current number of printers *after*
415 each add or delete printer RPC. Only Microsoft knows why... JRR020119
416 ********************************************************************/
418 uint32 update_c_setprinter(BOOL initialize)
420 int32 c_setprinter;
421 int32 printer_count = 0;
423 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
425 /* Traverse the tdb, counting the printers */
426 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
428 /* If initializing, set c_setprinter to current printers count
429 * otherwise, bump it by the current printer count
431 if (!initialize)
432 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
433 else
434 c_setprinter = printer_count;
436 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
437 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
439 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
441 return (uint32)c_setprinter;
444 /*******************************************************************
445 Get the spooler global c_setprinter, accounting for initialization.
446 ********************************************************************/
448 uint32 get_c_setprinter(void)
450 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
452 if (c_setprinter == (int32)-1)
453 c_setprinter = update_c_setprinter(True);
455 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
457 return (uint32)c_setprinter;
460 /****************************************************************************
461 Get builtin form struct list.
462 ****************************************************************************/
464 int get_builtin_ntforms(nt_forms_struct **list)
466 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
467 return sizeof(default_forms) / sizeof(default_forms[0]);
470 /****************************************************************************
471 get a builtin form struct
472 ****************************************************************************/
474 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
476 int i,count;
477 fstring form_name;
478 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
479 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
480 count = sizeof(default_forms) / sizeof(default_forms[0]);
481 for (i=0;i<count;i++) {
482 if (strequal(form_name,default_forms[i].name)) {
483 DEBUGADD(6,("Found builtin form %s \n", form_name));
484 memcpy(form,&default_forms[i],sizeof(*form));
485 break;
489 return (i !=count);
492 /****************************************************************************
493 get a form struct list
494 ****************************************************************************/
495 int get_ntforms(nt_forms_struct **list)
497 TDB_DATA kbuf, newkey, dbuf;
498 nt_forms_struct *tl;
499 nt_forms_struct form;
500 int ret;
501 int i;
502 int n = 0;
504 for (kbuf = tdb_firstkey(tdb_forms);
505 kbuf.dptr;
506 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
508 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
509 continue;
511 dbuf = tdb_fetch(tdb_forms, kbuf);
512 if (!dbuf.dptr)
513 continue;
515 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
516 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
517 &i, &form.flag, &form.width, &form.length, &form.left,
518 &form.top, &form.right, &form.bottom);
519 SAFE_FREE(dbuf.dptr);
520 if (ret != dbuf.dsize)
521 continue;
523 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
524 if (!tl) {
525 DEBUG(0,("get_ntforms: Realloc fail.\n"));
526 return 0;
528 *list = tl;
529 (*list)[n] = form;
530 n++;
534 return n;
537 /****************************************************************************
538 write a form struct list
539 ****************************************************************************/
540 int write_ntforms(nt_forms_struct **list, int number)
542 pstring buf, key;
543 int len;
544 TDB_DATA kbuf,dbuf;
545 int i;
547 for (i=0;i<number;i++) {
548 /* save index, so list is rebuilt in correct order */
549 len = tdb_pack(buf, sizeof(buf), "dddddddd",
550 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
551 (*list)[i].left, (*list)[i].top, (*list)[i].right,
552 (*list)[i].bottom);
553 if (len > sizeof(buf)) break;
554 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
555 kbuf.dsize = strlen(key)+1;
556 kbuf.dptr = key;
557 dbuf.dsize = len;
558 dbuf.dptr = buf;
559 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
562 return i;
565 /****************************************************************************
566 add a form struct at the end of the list
567 ****************************************************************************/
568 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
570 int n=0;
571 BOOL update;
572 fstring form_name;
573 nt_forms_struct *tl;
576 * NT tries to add forms even when
577 * they are already in the base
578 * only update the values if already present
581 update=False;
583 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
584 for (n=0; n<*count; n++) {
585 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
586 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
587 update=True;
588 break;
592 if (update==False) {
593 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
594 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
595 return False;
597 *list = tl;
598 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
599 (*count)++;
602 (*list)[n].flag=form->flags;
603 (*list)[n].width=form->size_x;
604 (*list)[n].length=form->size_y;
605 (*list)[n].left=form->left;
606 (*list)[n].top=form->top;
607 (*list)[n].right=form->right;
608 (*list)[n].bottom=form->bottom;
610 return True;
613 /****************************************************************************
614 Delete a named form struct.
615 ****************************************************************************/
617 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
619 pstring key;
620 TDB_DATA kbuf;
621 int n=0;
622 fstring form_name;
624 *ret = WERR_OK;
626 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
628 for (n=0; n<*count; n++) {
629 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
630 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
631 break;
635 if (n == *count) {
636 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
637 *ret = WERR_INVALID_PARAM;
638 return False;
641 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
642 kbuf.dsize = strlen(key)+1;
643 kbuf.dptr = key;
644 if (tdb_delete(tdb_forms, kbuf) != 0) {
645 *ret = WERR_NOMEM;
646 return False;
649 return True;
652 /****************************************************************************
653 Update a form struct.
654 ****************************************************************************/
656 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
658 int n=0;
659 fstring form_name;
660 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
662 DEBUG(106, ("[%s]\n", form_name));
663 for (n=0; n<count; n++) {
664 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
665 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
666 break;
669 if (n==count) return;
671 (*list)[n].flag=form->flags;
672 (*list)[n].width=form->size_x;
673 (*list)[n].length=form->size_y;
674 (*list)[n].left=form->left;
675 (*list)[n].top=form->top;
676 (*list)[n].right=form->right;
677 (*list)[n].bottom=form->bottom;
680 /****************************************************************************
681 Get the nt drivers list.
682 Traverse the database and look-up the matching names.
683 ****************************************************************************/
684 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
686 int total=0;
687 const char *short_archi;
688 fstring *fl;
689 pstring key;
690 TDB_DATA kbuf, newkey;
692 short_archi = get_short_archi(architecture);
693 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
695 for (kbuf = tdb_firstkey(tdb_drivers);
696 kbuf.dptr;
697 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
699 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
700 continue;
702 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
703 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
704 return -1;
706 else *list = fl;
708 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
709 total++;
712 return(total);
715 /****************************************************************************
716 function to do the mapping between the long architecture name and
717 the short one.
718 ****************************************************************************/
719 const char *get_short_archi(const char *long_archi)
721 int i=-1;
723 DEBUG(107,("Getting architecture dependant directory\n"));
724 do {
725 i++;
726 } while ( (archi_table[i].long_archi!=NULL ) &&
727 StrCaseCmp(long_archi, archi_table[i].long_archi) );
729 if (archi_table[i].long_archi==NULL) {
730 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
731 return NULL;
734 /* this might be client code - but shouldn't this be an fstrcpy etc? */
737 DEBUGADD(108,("index: [%d]\n", i));
738 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
739 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
741 return archi_table[i].short_archi;
744 /****************************************************************************
745 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
746 There are two case to be covered here: PE (Portable Executable) and NE (New
747 Executable) files. Both files support the same INFO structure, but PE files
748 store the signature in unicode, and NE files store it as !unicode.
749 returns -1 on error, 1 on version info found, and 0 on no version info found.
750 ****************************************************************************/
752 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
754 int i;
755 char *buf = NULL;
756 ssize_t byte_count;
758 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
759 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
760 fname, PE_HEADER_SIZE));
761 goto error_exit;
764 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
765 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
766 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
767 fname, (unsigned long)byte_count));
768 goto no_version_info;
771 /* Is this really a DOS header? */
772 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
773 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
774 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
775 goto no_version_info;
778 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
779 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
780 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
781 fname, errno));
782 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
783 goto no_version_info;
786 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
787 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
788 fname, (unsigned long)byte_count));
789 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
790 goto no_version_info;
793 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
794 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
795 unsigned int num_sections;
796 unsigned int section_table_bytes;
798 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
799 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
800 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
801 /* At this point, we assume the file is in error. It still could be somthing
802 * else besides a PE file, but it unlikely at this point.
804 goto error_exit;
807 /* get the section table */
808 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
809 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
810 if (section_table_bytes == 0)
811 goto error_exit;
813 SAFE_FREE(buf);
814 if ((buf=malloc(section_table_bytes)) == NULL) {
815 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
816 fname, section_table_bytes));
817 goto error_exit;
820 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
821 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
822 fname, (unsigned long)byte_count));
823 goto error_exit;
826 /* Iterate the section table looking for the resource section ".rsrc" */
827 for (i = 0; i < num_sections; i++) {
828 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
830 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
831 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
832 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
834 if (section_bytes == 0)
835 goto error_exit;
837 SAFE_FREE(buf);
838 if ((buf=malloc(section_bytes)) == NULL) {
839 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
840 fname, section_bytes));
841 goto error_exit;
844 /* Seek to the start of the .rsrc section info */
845 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
846 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
847 fname, errno));
848 goto error_exit;
851 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
852 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
853 fname, (unsigned long)byte_count));
854 goto error_exit;
857 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
858 goto error_exit;
860 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
861 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
862 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
863 /* Align to next long address */
864 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
866 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
867 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
868 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
870 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
871 fname, *major, *minor,
872 (*major>>16)&0xffff, *major&0xffff,
873 (*minor>>16)&0xffff, *minor&0xffff));
874 SAFE_FREE(buf);
875 return 1;
882 /* Version info not found, fall back to origin date/time */
883 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
884 SAFE_FREE(buf);
885 return 0;
887 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
888 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
889 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
890 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
891 /* At this point, we assume the file is in error. It still could be somthing
892 * else besides a NE file, but it unlikely at this point. */
893 goto error_exit;
896 /* Allocate a bit more space to speed up things */
897 SAFE_FREE(buf);
898 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
899 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
900 fname, PE_HEADER_SIZE));
901 goto error_exit;
904 /* This is a HACK! I got tired of trying to sort through the messy
905 * 'NE' file format. If anyone wants to clean this up please have at
906 * it, but this works. 'NE' files will eventually fade away. JRR */
907 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
908 /* Cover case that should not occur in a well formed 'NE' .dll file */
909 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
911 for(i=0; i<byte_count; i++) {
912 /* Fast skip past data that can't possibly match */
913 if (buf[i] != 'V') continue;
915 /* Potential match data crosses buf boundry, move it to beginning
916 * of buf, and fill the buf with as much as it will hold. */
917 if (i>byte_count-VS_VERSION_INFO_SIZE) {
918 int bc;
920 memcpy(buf, &buf[i], byte_count-i);
921 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
922 (byte_count-i))) < 0) {
924 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
925 fname, errno));
926 goto error_exit;
929 byte_count = bc + (byte_count - i);
930 if (byte_count<VS_VERSION_INFO_SIZE) break;
932 i = 0;
935 /* Check that the full signature string and the magic number that
936 * follows exist (not a perfect solution, but the chances that this
937 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
938 * twice, as it is simpler to read the code. */
939 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
940 /* Compute skip alignment to next long address */
941 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
942 sizeof(VS_SIGNATURE)) & 3;
943 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
945 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
946 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
947 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
948 fname, *major, *minor,
949 (*major>>16)&0xffff, *major&0xffff,
950 (*minor>>16)&0xffff, *minor&0xffff));
951 SAFE_FREE(buf);
952 return 1;
957 /* Version info not found, fall back to origin date/time */
958 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
959 SAFE_FREE(buf);
960 return 0;
962 } else
963 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
964 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
965 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
967 no_version_info:
968 SAFE_FREE(buf);
969 return 0;
971 error_exit:
972 SAFE_FREE(buf);
973 return -1;
976 /****************************************************************************
977 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
978 share one or more files. During the MS installation process files are checked
979 to insure that only a newer version of a shared file is installed over an
980 older version. There are several possibilities for this comparison. If there
981 is no previous version, the new one is newer (obviously). If either file is
982 missing the version info structure, compare the creation date (on Unix use
983 the modification date). Otherwise chose the numerically larger version number.
984 ****************************************************************************/
986 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
988 BOOL use_version = True;
989 pstring filepath;
991 uint32 new_major;
992 uint32 new_minor;
993 time_t new_create_time;
995 uint32 old_major;
996 uint32 old_minor;
997 time_t old_create_time;
999 int access_mode;
1000 int action;
1001 files_struct *fsp = NULL;
1002 SMB_STRUCT_STAT st;
1003 SMB_STRUCT_STAT stat_buf;
1004 BOOL bad_path;
1006 ZERO_STRUCT(st);
1007 ZERO_STRUCT(stat_buf);
1008 new_create_time = (time_t)0;
1009 old_create_time = (time_t)0;
1011 /* Get file version info (if available) for previous file (if it exists) */
1012 pstrcpy(filepath, old_file);
1014 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1016 fsp = open_file_shared(conn, filepath, &stat_buf,
1017 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1018 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1019 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1020 if (!fsp) {
1021 /* Old file not found, so by definition new file is in fact newer */
1022 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1023 filepath, errno));
1024 return True;
1026 } else {
1027 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1028 if (ret == -1) goto error_exit;
1030 if (!ret) {
1031 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1032 old_file));
1033 use_version = False;
1034 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1035 old_create_time = st.st_mtime;
1036 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1039 close_file(fsp, True);
1041 /* Get file version info (if available) for new file */
1042 pstrcpy(filepath, new_file);
1043 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1045 fsp = open_file_shared(conn, filepath, &stat_buf,
1046 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1047 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1048 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1049 if (!fsp) {
1050 /* New file not found, this shouldn't occur if the caller did its job */
1051 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1052 filepath, errno));
1053 goto error_exit;
1055 } else {
1056 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1057 if (ret == -1) goto error_exit;
1059 if (!ret) {
1060 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1061 new_file));
1062 use_version = False;
1063 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1064 new_create_time = st.st_mtime;
1065 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1068 close_file(fsp, True);
1070 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1071 /* Compare versions and choose the larger version number */
1072 if (new_major > old_major ||
1073 (new_major == old_major && new_minor > old_minor)) {
1075 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1076 return True;
1078 else {
1079 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1080 return False;
1083 } else {
1084 /* Compare modification time/dates and choose the newest time/date */
1085 if (new_create_time > old_create_time) {
1086 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1087 return True;
1089 else {
1090 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1091 return False;
1095 error_exit:
1096 if(fsp)
1097 close_file(fsp, True);
1098 return -1;
1101 /****************************************************************************
1102 Determine the correct cVersion associated with an architecture and driver
1103 ****************************************************************************/
1104 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1105 struct current_user *user, WERROR *perr)
1107 int cversion;
1108 int access_mode;
1109 int action;
1110 NTSTATUS nt_status;
1111 pstring driverpath;
1112 DATA_BLOB null_pw;
1113 fstring res_type;
1114 files_struct *fsp = NULL;
1115 BOOL bad_path;
1116 SMB_STRUCT_STAT st;
1117 connection_struct *conn;
1119 ZERO_STRUCT(st);
1121 *perr = WERR_INVALID_PARAM;
1123 /* If architecture is Windows 95/98/ME, the version is always 0. */
1124 if (strcmp(architecture, "WIN40") == 0) {
1125 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1126 *perr = WERR_OK;
1127 return 0;
1131 * Connect to the print$ share under the same account as the user connected
1132 * to the rpc pipe. Note we must still be root to do this.
1135 /* Null password is ok - we are already an authenticated user... */
1136 null_pw = data_blob(NULL, 0);
1137 fstrcpy(res_type, "A:");
1138 become_root();
1139 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1140 unbecome_root();
1142 if (conn == NULL) {
1143 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1144 *perr = ntstatus_to_werror(nt_status);
1145 return -1;
1148 /* We are temporarily becoming the connection user. */
1149 if (!become_user(conn, user->vuid)) {
1150 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1151 *perr = WERR_ACCESS_DENIED;
1152 return -1;
1155 /* Open the driver file (Portable Executable format) and determine the
1156 * deriver the cversion. */
1157 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1159 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1161 fsp = open_file_shared(conn, driverpath, &st,
1162 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1163 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1164 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1165 if (!fsp) {
1166 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1167 driverpath, errno));
1168 *perr = WERR_ACCESS_DENIED;
1169 goto error_exit;
1171 else {
1172 uint32 major;
1173 uint32 minor;
1174 int ret = get_file_version(fsp, driverpath, &major, &minor);
1175 if (ret == -1) goto error_exit;
1177 if (!ret) {
1178 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1179 goto error_exit;
1183 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1184 * for more details. Version in this case is not just the version of the
1185 * file, but the version in the sense of kernal mode (2) vs. user mode
1186 * (3) drivers. Other bits of the version fields are the version info.
1187 * JRR 010716
1189 cversion = major & 0x0000ffff;
1190 switch (cversion) {
1191 case 2: /* WinNT drivers */
1192 case 3: /* Win2K drivers */
1193 break;
1195 default:
1196 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1197 driverpath, cversion));
1198 goto error_exit;
1201 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1202 driverpath, major, minor));
1205 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1206 driverpath, cversion));
1208 close_file(fsp, True);
1209 close_cnum(conn, user->vuid);
1210 unbecome_user();
1211 *perr = WERR_OK;
1212 return cversion;
1215 error_exit:
1217 if(fsp)
1218 close_file(fsp, True);
1220 close_cnum(conn, user->vuid);
1221 unbecome_user();
1222 return -1;
1225 /****************************************************************************
1226 ****************************************************************************/
1227 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1228 struct current_user *user)
1230 const char *architecture;
1231 fstring new_name;
1232 char *p;
1233 int i;
1234 WERROR err;
1236 /* clean up the driver name.
1237 * we can get .\driver.dll
1238 * or worse c:\windows\system\driver.dll !
1240 /* using an intermediate string to not have overlaping memcpy()'s */
1241 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1242 fstrcpy(new_name, p+1);
1243 fstrcpy(driver->driverpath, new_name);
1246 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1247 fstrcpy(new_name, p+1);
1248 fstrcpy(driver->datafile, new_name);
1251 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1252 fstrcpy(new_name, p+1);
1253 fstrcpy(driver->configfile, new_name);
1256 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1257 fstrcpy(new_name, p+1);
1258 fstrcpy(driver->helpfile, new_name);
1261 if (driver->dependentfiles) {
1262 for (i=0; *driver->dependentfiles[i]; i++) {
1263 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1264 fstrcpy(new_name, p+1);
1265 fstrcpy(driver->dependentfiles[i], new_name);
1270 architecture = get_short_archi(driver->environment);
1272 /* jfm:7/16/2000 the client always sends the cversion=0.
1273 * The server should check which version the driver is by reading
1274 * the PE header of driver->driverpath.
1276 * For Windows 95/98 the version is 0 (so the value sent is correct)
1277 * For Windows NT (the architecture doesn't matter)
1278 * NT 3.1: cversion=0
1279 * NT 3.5/3.51: cversion=1
1280 * NT 4: cversion=2
1281 * NT2K: cversion=3
1283 if ((driver->cversion = get_correct_cversion( architecture,
1284 driver->driverpath, user, &err)) == -1)
1285 return err;
1287 return WERR_OK;
1290 /****************************************************************************
1291 ****************************************************************************/
1292 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1294 const char *architecture;
1295 fstring new_name;
1296 char *p;
1297 int i;
1298 WERROR err;
1300 /* clean up the driver name.
1301 * we can get .\driver.dll
1302 * or worse c:\windows\system\driver.dll !
1304 /* using an intermediate string to not have overlaping memcpy()'s */
1305 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1306 fstrcpy(new_name, p+1);
1307 fstrcpy(driver->driverpath, new_name);
1310 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1311 fstrcpy(new_name, p+1);
1312 fstrcpy(driver->datafile, new_name);
1315 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1316 fstrcpy(new_name, p+1);
1317 fstrcpy(driver->configfile, new_name);
1320 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1321 fstrcpy(new_name, p+1);
1322 fstrcpy(driver->helpfile, new_name);
1325 if (driver->dependentfiles) {
1326 for (i=0; *driver->dependentfiles[i]; i++) {
1327 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1328 fstrcpy(new_name, p+1);
1329 fstrcpy(driver->dependentfiles[i], new_name);
1334 architecture = get_short_archi(driver->environment);
1336 /* jfm:7/16/2000 the client always sends the cversion=0.
1337 * The server should check which version the driver is by reading
1338 * the PE header of driver->driverpath.
1340 * For Windows 95/98 the version is 0 (so the value sent is correct)
1341 * For Windows NT (the architecture doesn't matter)
1342 * NT 3.1: cversion=0
1343 * NT 3.5/3.51: cversion=1
1344 * NT 4: cversion=2
1345 * NT2K: cversion=3
1347 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1348 return err;
1350 return WERR_OK;
1353 /****************************************************************************
1354 ****************************************************************************/
1355 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1356 uint32 level, struct current_user *user)
1358 switch (level) {
1359 case 3:
1361 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1362 driver=driver_abstract.info_3;
1363 return clean_up_driver_struct_level_3(driver, user);
1365 case 6:
1367 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1368 driver=driver_abstract.info_6;
1369 return clean_up_driver_struct_level_6(driver, user);
1371 default:
1372 return WERR_INVALID_PARAM;
1376 /****************************************************************************
1377 This function sucks and should be replaced. JRA.
1378 ****************************************************************************/
1380 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1382 dst->cversion = src->version;
1384 fstrcpy( dst->name, src->name);
1385 fstrcpy( dst->environment, src->environment);
1386 fstrcpy( dst->driverpath, src->driverpath);
1387 fstrcpy( dst->datafile, src->datafile);
1388 fstrcpy( dst->configfile, src->configfile);
1389 fstrcpy( dst->helpfile, src->helpfile);
1390 fstrcpy( dst->monitorname, src->monitorname);
1391 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1392 dst->dependentfiles = src->dependentfiles;
1395 #if 0 /* Debugging function */
1397 static char* ffmt(unsigned char *c){
1398 int i;
1399 static char ffmt_str[17];
1401 for (i=0; i<16; i++) {
1402 if ((c[i] < ' ') || (c[i] > '~'))
1403 ffmt_str[i]='.';
1404 else
1405 ffmt_str[i]=c[i];
1407 ffmt_str[16]='\0';
1408 return ffmt_str;
1411 #endif
1413 /****************************************************************************
1414 ****************************************************************************/
1415 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1416 struct current_user *user, WERROR *perr)
1418 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1419 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1420 const char *architecture;
1421 pstring new_dir;
1422 pstring old_name;
1423 pstring new_name;
1424 DATA_BLOB null_pw;
1425 connection_struct *conn;
1426 NTSTATUS nt_status;
1427 pstring inbuf;
1428 pstring outbuf;
1429 fstring res_type;
1430 BOOL bad_path;
1431 SMB_STRUCT_STAT st;
1432 int ver = 0;
1433 int i;
1435 memset(inbuf, '\0', sizeof(inbuf));
1436 memset(outbuf, '\0', sizeof(outbuf));
1437 *perr = WERR_OK;
1439 if (level==3)
1440 driver=driver_abstract.info_3;
1441 else if (level==6) {
1442 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1443 driver = &converted_driver;
1444 } else {
1445 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1446 return False;
1449 architecture = get_short_archi(driver->environment);
1452 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1453 * Note we must be root to do this.
1456 null_pw = data_blob(NULL, 0);
1457 fstrcpy(res_type, "A:");
1458 become_root();
1459 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1460 unbecome_root();
1462 if (conn == NULL) {
1463 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1464 *perr = ntstatus_to_werror(nt_status);
1465 return False;
1469 * Save who we are - we are temporarily becoming the connection user.
1472 if (!become_user(conn, conn->vuid)) {
1473 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1474 return False;
1478 * make the directories version and version\driver_name
1479 * under the architecture directory.
1481 DEBUG(5,("Creating first directory\n"));
1482 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1483 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1484 mkdir_internal(conn, new_dir);
1486 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1487 * listed for this driver which has already been moved, skip it (note:
1488 * drivers may list the same file name several times. Then check if the
1489 * file already exists in archi\cversion\, if so, check that the version
1490 * info (or time stamps if version info is unavailable) is newer (or the
1491 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1492 * Otherwise, delete the file.
1494 * If a file is not moved to archi\cversion\ because of an error, all the
1495 * rest of the 'unmoved' driver files are removed from archi\. If one or
1496 * more of the driver's files was already moved to archi\cversion\, it
1497 * potentially leaves the driver in a partially updated state. Version
1498 * trauma will most likely occur if an client attempts to use any printer
1499 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1500 * done is appropriate... later JRR
1503 DEBUG(5,("Moving files now !\n"));
1505 if (driver->driverpath && strlen(driver->driverpath)) {
1506 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1507 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1508 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1509 NTSTATUS status;
1510 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1511 status = rename_internals(conn, new_name, old_name, 0, True);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1514 new_name, old_name));
1515 *perr = ntstatus_to_werror(status);
1516 unlink_internals(conn, 0, new_name);
1517 ver = -1;
1519 } else {
1520 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1521 unlink_internals(conn, 0, new_name);
1525 if (driver->datafile && strlen(driver->datafile)) {
1526 if (!strequal(driver->datafile, driver->driverpath)) {
1527 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1528 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1529 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1530 NTSTATUS status;
1531 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1532 status = rename_internals(conn, new_name, old_name, 0, True);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1535 new_name, old_name));
1536 *perr = ntstatus_to_werror(status);
1537 unlink_internals(conn, 0, new_name);
1538 ver = -1;
1540 } else {
1541 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1542 unlink_internals(conn, 0, new_name);
1547 if (driver->configfile && strlen(driver->configfile)) {
1548 if (!strequal(driver->configfile, driver->driverpath) &&
1549 !strequal(driver->configfile, driver->datafile)) {
1550 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1551 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1552 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1553 NTSTATUS status;
1554 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1555 status = rename_internals(conn, new_name, old_name, 0, True);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1558 new_name, old_name));
1559 *perr = ntstatus_to_werror(status);
1560 unlink_internals(conn, 0, new_name);
1561 ver = -1;
1563 } else {
1564 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1565 unlink_internals(conn, 0, new_name);
1570 if (driver->helpfile && strlen(driver->helpfile)) {
1571 if (!strequal(driver->helpfile, driver->driverpath) &&
1572 !strequal(driver->helpfile, driver->datafile) &&
1573 !strequal(driver->helpfile, driver->configfile)) {
1574 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1575 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1576 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1577 NTSTATUS status;
1578 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1579 status = rename_internals(conn, new_name, old_name, 0, True);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1582 new_name, old_name));
1583 *perr = ntstatus_to_werror(status);
1584 unlink_internals(conn, 0, new_name);
1585 ver = -1;
1587 } else {
1588 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1589 unlink_internals(conn, 0, new_name);
1594 if (driver->dependentfiles) {
1595 for (i=0; *driver->dependentfiles[i]; i++) {
1596 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1597 !strequal(driver->dependentfiles[i], driver->datafile) &&
1598 !strequal(driver->dependentfiles[i], driver->configfile) &&
1599 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1600 int j;
1601 for (j=0; j < i; j++) {
1602 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1603 goto NextDriver;
1607 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1608 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1609 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1610 NTSTATUS status;
1611 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1612 status = rename_internals(conn, new_name, old_name, 0, True);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1615 new_name, old_name));
1616 *perr = ntstatus_to_werror(status);
1617 unlink_internals(conn, 0, new_name);
1618 ver = -1;
1620 } else {
1621 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1622 unlink_internals(conn, 0, new_name);
1625 NextDriver: ;
1629 close_cnum(conn, user->vuid);
1630 unbecome_user();
1632 return ver == -1 ? False : True;
1635 /****************************************************************************
1636 ****************************************************************************/
1637 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1639 int len, buflen;
1640 const char *architecture;
1641 pstring directory;
1642 fstring temp_name;
1643 pstring key;
1644 char *buf;
1645 int i, ret;
1646 TDB_DATA kbuf, dbuf;
1648 architecture = get_short_archi(driver->environment);
1650 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1651 * \\server is added in the rpc server layer.
1652 * It does make sense to NOT store the server's name in the printer TDB.
1655 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1657 /* .inf files do not always list a file for each of the four standard files.
1658 * Don't prepend a path to a null filename, or client claims:
1659 * "The server on which the printer resides does not have a suitable
1660 * <printer driver name> printer driver installed. Click OK if you
1661 * wish to install the driver on your local machine."
1663 if (strlen(driver->driverpath)) {
1664 fstrcpy(temp_name, driver->driverpath);
1665 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1668 if (strlen(driver->datafile)) {
1669 fstrcpy(temp_name, driver->datafile);
1670 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1673 if (strlen(driver->configfile)) {
1674 fstrcpy(temp_name, driver->configfile);
1675 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1678 if (strlen(driver->helpfile)) {
1679 fstrcpy(temp_name, driver->helpfile);
1680 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1683 if (driver->dependentfiles) {
1684 for (i=0; *driver->dependentfiles[i]; i++) {
1685 fstrcpy(temp_name, driver->dependentfiles[i]);
1686 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1690 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1692 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1694 buf = NULL;
1695 len = buflen = 0;
1697 again:
1698 len = 0;
1699 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1700 driver->cversion,
1701 driver->name,
1702 driver->environment,
1703 driver->driverpath,
1704 driver->datafile,
1705 driver->configfile,
1706 driver->helpfile,
1707 driver->monitorname,
1708 driver->defaultdatatype);
1710 if (driver->dependentfiles) {
1711 for (i=0; *driver->dependentfiles[i]; i++) {
1712 len += tdb_pack(buf+len, buflen-len, "f",
1713 driver->dependentfiles[i]);
1717 if (len != buflen) {
1718 char *tb;
1720 tb = (char *)Realloc(buf, len);
1721 if (!tb) {
1722 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1723 ret = -1;
1724 goto done;
1726 else buf = tb;
1727 buflen = len;
1728 goto again;
1732 kbuf.dptr = key;
1733 kbuf.dsize = strlen(key)+1;
1734 dbuf.dptr = buf;
1735 dbuf.dsize = len;
1737 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1739 done:
1740 if (ret)
1741 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1743 SAFE_FREE(buf);
1744 return ret;
1747 /****************************************************************************
1748 ****************************************************************************/
1749 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1751 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1753 ZERO_STRUCT(info3);
1754 info3.cversion = driver->version;
1755 fstrcpy(info3.name,driver->name);
1756 fstrcpy(info3.environment,driver->environment);
1757 fstrcpy(info3.driverpath,driver->driverpath);
1758 fstrcpy(info3.datafile,driver->datafile);
1759 fstrcpy(info3.configfile,driver->configfile);
1760 fstrcpy(info3.helpfile,driver->helpfile);
1761 fstrcpy(info3.monitorname,driver->monitorname);
1762 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1763 info3.dependentfiles = driver->dependentfiles;
1765 return add_a_printer_driver_3(&info3);
1769 /****************************************************************************
1770 ****************************************************************************/
1771 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1773 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1775 ZERO_STRUCT(info);
1777 fstrcpy(info.name, driver);
1778 fstrcpy(info.defaultdatatype, "RAW");
1780 fstrcpy(info.driverpath, "");
1781 fstrcpy(info.datafile, "");
1782 fstrcpy(info.configfile, "");
1783 fstrcpy(info.helpfile, "");
1785 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1786 return WERR_NOMEM;
1788 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1789 fstrcpy(info.dependentfiles[0], "");
1791 *info_ptr = memdup(&info, sizeof(info));
1793 return WERR_OK;
1796 /****************************************************************************
1797 ****************************************************************************/
1798 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1800 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1801 TDB_DATA kbuf, dbuf;
1802 const char *architecture;
1803 int len = 0;
1804 int i;
1805 pstring key;
1807 ZERO_STRUCT(driver);
1809 architecture = get_short_archi(arch);
1811 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1813 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1814 version = 0;
1816 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1818 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1820 kbuf.dptr = key;
1821 kbuf.dsize = strlen(key)+1;
1823 dbuf = tdb_fetch(tdb_drivers, kbuf);
1824 if (!dbuf.dptr)
1825 return WERR_UNKNOWN_PRINTER_DRIVER;
1827 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1828 &driver.cversion,
1829 driver.name,
1830 driver.environment,
1831 driver.driverpath,
1832 driver.datafile,
1833 driver.configfile,
1834 driver.helpfile,
1835 driver.monitorname,
1836 driver.defaultdatatype);
1838 i=0;
1839 while (len < dbuf.dsize) {
1840 fstring *tddfs;
1842 tddfs = (fstring *)Realloc(driver.dependentfiles,
1843 sizeof(fstring)*(i+2));
1844 if (tddfs == NULL) {
1845 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1846 break;
1848 else driver.dependentfiles = tddfs;
1850 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1851 &driver.dependentfiles[i]);
1852 i++;
1855 if (driver.dependentfiles != NULL)
1856 fstrcpy(driver.dependentfiles[i], "");
1858 SAFE_FREE(dbuf.dptr);
1860 if (len != dbuf.dsize) {
1861 SAFE_FREE(driver.dependentfiles);
1863 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1866 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1868 return WERR_OK;
1871 /****************************************************************************
1872 Debugging function, dump at level 6 the struct in the logs.
1873 ****************************************************************************/
1875 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1877 uint32 result;
1878 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1879 int i;
1881 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1883 switch (level)
1885 case 3:
1887 if (driver.info_3 == NULL)
1888 result=5;
1889 else {
1890 info3=driver.info_3;
1892 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1893 DEBUGADD(20,("name:[%s]\n", info3->name));
1894 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1895 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1896 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1897 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1898 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1899 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1900 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1902 for (i=0; info3->dependentfiles &&
1903 *info3->dependentfiles[i]; i++) {
1904 DEBUGADD(20,("dependentfile:[%s]\n",
1905 info3->dependentfiles[i]));
1907 result=0;
1909 break;
1911 default:
1912 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1913 result=1;
1914 break;
1917 return result;
1920 /****************************************************************************
1921 ****************************************************************************/
1922 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1924 int len = 0;
1926 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1928 if (!nt_devmode)
1929 return len;
1931 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1932 nt_devmode->devicename,
1933 nt_devmode->formname,
1935 nt_devmode->specversion,
1936 nt_devmode->driverversion,
1937 nt_devmode->size,
1938 nt_devmode->driverextra,
1939 nt_devmode->orientation,
1940 nt_devmode->papersize,
1941 nt_devmode->paperlength,
1942 nt_devmode->paperwidth,
1943 nt_devmode->scale,
1944 nt_devmode->copies,
1945 nt_devmode->defaultsource,
1946 nt_devmode->printquality,
1947 nt_devmode->color,
1948 nt_devmode->duplex,
1949 nt_devmode->yresolution,
1950 nt_devmode->ttoption,
1951 nt_devmode->collate,
1952 nt_devmode->logpixels,
1954 nt_devmode->fields,
1955 nt_devmode->bitsperpel,
1956 nt_devmode->pelswidth,
1957 nt_devmode->pelsheight,
1958 nt_devmode->displayflags,
1959 nt_devmode->displayfrequency,
1960 nt_devmode->icmmethod,
1961 nt_devmode->icmintent,
1962 nt_devmode->mediatype,
1963 nt_devmode->dithertype,
1964 nt_devmode->reserved1,
1965 nt_devmode->reserved2,
1966 nt_devmode->panningwidth,
1967 nt_devmode->panningheight,
1968 nt_devmode->private);
1971 if (nt_devmode->private) {
1972 len += tdb_pack(buf+len, buflen-len, "B",
1973 nt_devmode->driverextra,
1974 nt_devmode->private);
1977 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1979 return len;
1982 /****************************************************************************
1983 Pack all values in all printer keys
1984 ***************************************************************************/
1986 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1988 int len = 0;
1989 int i, j;
1990 REGISTRY_VALUE *val;
1991 REGVAL_CTR *val_ctr;
1992 pstring path;
1993 int num_values;
1995 if ( !data )
1996 return 0;
1998 /* loop over all keys */
2000 for ( i=0; i<data->num_keys; i++ ) {
2001 val_ctr = &data->keys[i].values;
2002 num_values = regval_ctr_numvals( val_ctr );
2004 /* loop over all values */
2006 for ( j=0; j<num_values; j++ ) {
2007 /* pathname should be stored as <key>\<value> */
2009 val = regval_ctr_specific_value( val_ctr, j );
2010 pstrcpy( path, data->keys[i].name );
2011 pstrcat( path, "\\" );
2012 pstrcat( path, regval_name(val) );
2014 len += tdb_pack(buf+len, buflen-len, "pPdB",
2015 val,
2016 path,
2017 regval_type(val),
2018 regval_size(val),
2019 regval_data_p(val) );
2024 /* terminator */
2026 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2028 return len;
2032 /****************************************************************************
2033 Delete a printer - this just deletes the printer info file, any open
2034 handles are not affected.
2035 ****************************************************************************/
2037 uint32 del_a_printer(char *sharename)
2039 pstring key;
2040 TDB_DATA kbuf;
2042 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2044 kbuf.dptr=key;
2045 kbuf.dsize=strlen(key)+1;
2047 tdb_delete(tdb_printers, kbuf);
2048 return 0;
2051 /****************************************************************************
2052 ****************************************************************************/
2053 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2055 pstring key;
2056 char *buf;
2057 int buflen, len;
2058 WERROR ret;
2059 TDB_DATA kbuf, dbuf;
2062 * in addprinter: no servername and the printer is the name
2063 * in setprinter: servername is \\server
2064 * and printer is \\server\\printer
2066 * Samba manages only local printers.
2067 * we currently don't support things like i
2068 * path=\\other_server\printer
2070 * We only store the printername, not \\server\printername
2073 if ( info->servername[0] != '\0' ) {
2074 trim_string(info->printername, info->servername, NULL);
2075 trim_char(info->printername, '\\', '\0');
2076 info->servername[0]='\0';
2080 * JFM: one day I'll forget.
2081 * below that's info->portname because that's the SAMBA sharename
2082 * and I made NT 'thinks' it's the portname
2083 * the info->sharename is the thing you can name when you add a printer
2084 * that's the short-name when you create shared printer for 95/98
2085 * So I've made a limitation in SAMBA: you can only have 1 printer model
2086 * behind a SAMBA share.
2089 buf = NULL;
2090 buflen = 0;
2092 again:
2093 len = 0;
2094 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2095 info->attributes,
2096 info->priority,
2097 info->default_priority,
2098 info->starttime,
2099 info->untiltime,
2100 info->status,
2101 info->cjobs,
2102 info->averageppm,
2103 info->changeid,
2104 info->c_setprinter,
2105 info->setuptime,
2106 info->servername,
2107 info->printername,
2108 info->sharename,
2109 info->portname,
2110 info->drivername,
2111 info->comment,
2112 info->location,
2113 info->sepfile,
2114 info->printprocessor,
2115 info->datatype,
2116 info->parameters);
2118 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2120 len += pack_values( &info->data, buf+len, buflen-len );
2122 if (buflen != len) {
2123 char *tb;
2125 tb = (char *)Realloc(buf, len);
2126 if (!tb) {
2127 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2128 ret = WERR_NOMEM;
2129 goto done;
2131 else buf = tb;
2132 buflen = len;
2133 goto again;
2137 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2139 kbuf.dptr = key;
2140 kbuf.dsize = strlen(key)+1;
2141 dbuf.dptr = buf;
2142 dbuf.dsize = len;
2144 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2146 done:
2147 if (!W_ERROR_IS_OK(ret))
2148 DEBUG(8, ("error updating printer to tdb on disk\n"));
2150 SAFE_FREE(buf);
2152 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2153 info->sharename, info->drivername, info->portname, len));
2155 return ret;
2159 /****************************************************************************
2160 Malloc and return an NT devicemode.
2161 ****************************************************************************/
2163 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2166 char adevice[MAXDEVICENAME];
2167 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2169 if (nt_devmode == NULL) {
2170 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2171 return NULL;
2174 ZERO_STRUCTP(nt_devmode);
2176 safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2177 fstrcpy(nt_devmode->devicename, adevice);
2179 fstrcpy(nt_devmode->formname, "Letter");
2181 nt_devmode->specversion = 0x0401;
2182 nt_devmode->driverversion = 0x0400;
2183 nt_devmode->size = 0x00DC;
2184 nt_devmode->driverextra = 0x0000;
2185 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2186 DEFAULTSOURCE | COPIES | SCALE |
2187 PAPERSIZE | ORIENTATION;
2188 nt_devmode->orientation = 1;
2189 nt_devmode->papersize = PAPER_LETTER;
2190 nt_devmode->paperlength = 0;
2191 nt_devmode->paperwidth = 0;
2192 nt_devmode->scale = 0x64;
2193 nt_devmode->copies = 1;
2194 nt_devmode->defaultsource = BIN_FORMSOURCE;
2195 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2196 nt_devmode->color = COLOR_MONOCHROME;
2197 nt_devmode->duplex = DUP_SIMPLEX;
2198 nt_devmode->yresolution = 0;
2199 nt_devmode->ttoption = TT_SUBDEV;
2200 nt_devmode->collate = COLLATE_FALSE;
2201 nt_devmode->icmmethod = 0;
2202 nt_devmode->icmintent = 0;
2203 nt_devmode->mediatype = 0;
2204 nt_devmode->dithertype = 0;
2206 /* non utilisés par un driver d'imprimante */
2207 nt_devmode->logpixels = 0;
2208 nt_devmode->bitsperpel = 0;
2209 nt_devmode->pelswidth = 0;
2210 nt_devmode->pelsheight = 0;
2211 nt_devmode->displayflags = 0;
2212 nt_devmode->displayfrequency = 0;
2213 nt_devmode->reserved1 = 0;
2214 nt_devmode->reserved2 = 0;
2215 nt_devmode->panningwidth = 0;
2216 nt_devmode->panningheight = 0;
2218 nt_devmode->private = NULL;
2219 return nt_devmode;
2222 /****************************************************************************
2223 Deepcopy an NT devicemode.
2224 ****************************************************************************/
2226 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2228 NT_DEVICEMODE *new_nt_devicemode = NULL;
2230 if ( !nt_devicemode )
2231 return NULL;
2233 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2234 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2235 return NULL;
2238 new_nt_devicemode->private = NULL;
2239 if (nt_devicemode->private != NULL) {
2240 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2241 SAFE_FREE(new_nt_devicemode);
2242 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2243 return NULL;
2247 return new_nt_devicemode;
2250 /****************************************************************************
2251 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2252 ****************************************************************************/
2254 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2256 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2258 if(nt_devmode == NULL)
2259 return;
2261 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2263 SAFE_FREE(nt_devmode->private);
2264 SAFE_FREE(*devmode_ptr);
2267 /****************************************************************************
2268 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2269 ****************************************************************************/
2270 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2272 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2273 NT_PRINTER_DATA *data;
2274 int i;
2276 if ( !info )
2277 return;
2279 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2281 free_nt_devicemode(&info->devmode);
2283 /* clean up all registry keys */
2285 data = &info->data;
2286 for ( i=0; i<data->num_keys; i++ ) {
2287 SAFE_FREE( data->keys[i].name );
2288 regval_ctr_destroy( &data->keys[i].values );
2290 SAFE_FREE( data->keys );
2292 /* finally the top level structure */
2294 SAFE_FREE( *info_ptr );
2298 /****************************************************************************
2299 ****************************************************************************/
2300 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2302 int len = 0;
2303 int extra_len = 0;
2304 NT_DEVICEMODE devmode;
2306 ZERO_STRUCT(devmode);
2308 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2310 if (!*nt_devmode) return len;
2312 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2313 devmode.devicename,
2314 devmode.formname,
2316 &devmode.specversion,
2317 &devmode.driverversion,
2318 &devmode.size,
2319 &devmode.driverextra,
2320 &devmode.orientation,
2321 &devmode.papersize,
2322 &devmode.paperlength,
2323 &devmode.paperwidth,
2324 &devmode.scale,
2325 &devmode.copies,
2326 &devmode.defaultsource,
2327 &devmode.printquality,
2328 &devmode.color,
2329 &devmode.duplex,
2330 &devmode.yresolution,
2331 &devmode.ttoption,
2332 &devmode.collate,
2333 &devmode.logpixels,
2335 &devmode.fields,
2336 &devmode.bitsperpel,
2337 &devmode.pelswidth,
2338 &devmode.pelsheight,
2339 &devmode.displayflags,
2340 &devmode.displayfrequency,
2341 &devmode.icmmethod,
2342 &devmode.icmintent,
2343 &devmode.mediatype,
2344 &devmode.dithertype,
2345 &devmode.reserved1,
2346 &devmode.reserved2,
2347 &devmode.panningwidth,
2348 &devmode.panningheight,
2349 &devmode.private);
2351 if (devmode.private) {
2352 /* the len in tdb_unpack is an int value and
2353 * devmode.driverextra is only a short
2355 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2356 devmode.driverextra=(uint16)extra_len;
2358 /* check to catch an invalid TDB entry so we don't segfault */
2359 if (devmode.driverextra == 0) {
2360 devmode.private = NULL;
2364 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2366 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2367 if (devmode.private)
2368 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2370 return len;
2373 /****************************************************************************
2374 Allocate and initialize a new slot.
2375 ***************************************************************************/
2377 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2379 NT_PRINTER_KEY *d;
2380 int key_index;
2382 if ( !data || !name )
2383 return -1;
2385 /* allocate another slot in the NT_PRINTER_KEY array */
2387 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2388 if ( d )
2389 data->keys = d;
2391 key_index = data->num_keys;
2393 /* initialze new key */
2395 data->num_keys++;
2396 data->keys[key_index].name = strdup( name );
2398 ZERO_STRUCTP( &data->keys[key_index].values );
2400 regval_ctr_init( &data->keys[key_index].values );
2402 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2404 return key_index;
2407 /****************************************************************************
2408 search for a registry key name in the existing printer data
2409 ***************************************************************************/
2411 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2413 int key_index = -1;
2414 int i;
2416 if ( !data || !name )
2417 return -1;
2419 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2421 /* loop over all existing keys */
2423 for ( i=0; i<data->num_keys; i++ ) {
2424 if ( strequal(data->keys[i].name, name) ) {
2425 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2426 key_index = i;
2427 break;
2432 return key_index;
2435 /****************************************************************************
2436 ***************************************************************************/
2438 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2440 int i, j;
2441 int key_len;
2442 int num_subkeys = 0;
2443 char *p;
2444 fstring *ptr, *subkeys_ptr = NULL;
2445 fstring subkeyname;
2447 if ( !data )
2448 return 0;
2450 for ( i=0; i<data->num_keys; i++ ) {
2451 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2452 /* match sure it is a subkey and not the key itself */
2454 key_len = strlen( key );
2455 if ( strlen(data->keys[i].name) == key_len )
2456 continue;
2458 /* get subkey path */
2460 p = data->keys[i].name + key_len;
2461 if ( *p == '\\' )
2462 p++;
2463 fstrcpy( subkeyname, p );
2464 if ( (p = strchr( subkeyname, '\\' )) )
2465 *p = '\0';
2467 /* don't add a key more than once */
2469 for ( j=0; j<num_subkeys; j++ ) {
2470 if ( strequal( subkeys_ptr[j], subkeyname ) )
2471 break;
2474 if ( j != num_subkeys )
2475 continue;
2477 /* found a match, so allocate space and copy the name */
2479 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2480 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2481 num_subkeys+1));
2482 SAFE_FREE( subkeys );
2483 return 0;
2486 subkeys_ptr = ptr;
2487 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2488 num_subkeys++;
2493 /* tag of the end */
2495 if (num_subkeys)
2496 fstrcpy(subkeys_ptr[num_subkeys], "" );
2498 *subkeys = subkeys_ptr;
2500 return num_subkeys;
2503 #ifdef HAVE_ADS
2504 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2505 const char *sz)
2507 smb_ucs2_t conv_str[1024];
2508 size_t str_size;
2510 regval_ctr_delvalue(ctr, val_name);
2511 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2512 STR_TERMINATE | STR_NOALIGN);
2513 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2514 (char *) conv_str, str_size);
2517 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2518 uint32 dword)
2520 regval_ctr_delvalue(ctr, val_name);
2521 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2522 (char *) &dword, sizeof(dword));
2525 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2526 BOOL b)
2528 uint8 bin_bool = (b ? 1 : 0);
2529 regval_ctr_delvalue(ctr, val_name);
2530 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2531 (char *) &bin_bool, sizeof(bin_bool));
2534 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2535 const char *multi_sz)
2537 smb_ucs2_t *conv_strs = NULL;
2538 size_t str_size;
2540 /* a multi-sz has to have a null string terminator, i.e., the last
2541 string must be followed by two nulls */
2542 str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2543 conv_strs = calloc(str_size, 1);
2545 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2546 STR_TERMINATE | STR_NOALIGN);
2548 regval_ctr_delvalue(ctr, val_name);
2549 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2550 (char *) conv_strs, str_size);
2551 safe_free(conv_strs);
2555 /****************************************************************************
2556 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2558 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2559 * @return BOOL indicating success or failure
2560 ***************************************************************************/
2562 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2564 REGVAL_CTR *ctr = NULL;
2565 fstring longname;
2566 char *allocated_string = NULL;
2567 const char *ascii_str;
2568 int i;
2570 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2571 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2572 ctr = &info2->data.keys[i].values;
2574 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2575 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2577 get_mydnsfullname(longname);
2578 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2580 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2581 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2582 SAFE_FREE(allocated_string);
2584 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2585 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2586 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2587 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2588 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2589 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2590 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2591 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2592 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2594 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2595 (info2->attributes &
2596 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2598 switch (info2->attributes & 0x3) {
2599 case 0:
2600 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2601 break;
2602 case 1:
2603 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2604 break;
2605 case 2:
2606 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2607 break;
2608 default:
2609 ascii_str = "unknown";
2611 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2613 return True;
2616 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2617 struct uuid guid)
2619 int i;
2620 REGVAL_CTR *ctr=NULL;
2622 /* find the DsSpooler key */
2623 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2624 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2625 ctr = &info2->data.keys[i].values;
2627 regval_ctr_delvalue(ctr, "objectGUID");
2628 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2629 (char *) &guid, sizeof(struct uuid));
2632 static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2634 ADS_STATUS ads_rc;
2635 TALLOC_CTX *ctx = talloc_init("publish_it");
2636 ADS_MODLIST mods = ads_init_mods(ctx);
2637 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2638 char *srv_dn_utf8, **srv_cn_utf8;
2639 void *res = NULL;
2640 ADS_STRUCT *ads;
2641 const char *attrs[] = {"objectGUID", NULL};
2642 struct uuid guid;
2643 WERROR win_rc = WERR_OK;
2645 ZERO_STRUCT(guid);
2646 /* set the DsSpooler info and attributes */
2647 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2648 return WERR_NOMEM;
2649 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2650 win_rc = mod_a_printer(*printer, 2);
2651 if (!W_ERROR_IS_OK(win_rc)) {
2652 DEBUG(3, ("err %d saving data\n",
2653 W_ERROR_V(win_rc)));
2654 return win_rc;
2657 /* Build the ads mods */
2658 get_local_printer_publishing_data(ctx, &mods,
2659 &printer->info_2->data);
2660 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2661 printer->info_2->sharename);
2663 /* initial ads structure */
2665 ads = ads_init(NULL, NULL, NULL);
2666 if (!ads) {
2667 DEBUG(3, ("ads_init() failed\n"));
2668 return WERR_SERVER_UNAVAILABLE;
2670 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2671 SAFE_FREE(ads->auth.password);
2672 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2673 NULL, NULL);
2675 /* ads_connect() will find the DC for us */
2676 ads_rc = ads_connect(ads);
2677 if (!ADS_ERR_OK(ads_rc)) {
2678 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2679 ads_destroy(&ads);
2680 return WERR_ACCESS_DENIED;
2683 /* figure out where to publish */
2684 ads_find_machine_acct(ads, &res, global_myname());
2686 /* We use ldap_get_dn here as we need the answer
2687 * in utf8 to call ldap_explode_dn(). JRA. */
2689 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2690 if (!srv_dn_utf8) {
2691 ads_destroy(&ads);
2692 return WERR_SERVER_UNAVAILABLE;
2694 ads_msgfree(ads, res);
2695 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2696 if (!srv_cn_utf8) {
2697 ldap_memfree(srv_dn_utf8);
2698 ads_destroy(&ads);
2699 return WERR_SERVER_UNAVAILABLE;
2701 /* Now convert to CH_UNIX. */
2702 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2703 ldap_memfree(srv_dn_utf8);
2704 ldap_memfree(srv_cn_utf8);
2705 ads_destroy(&ads);
2706 return WERR_SERVER_UNAVAILABLE;
2708 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2709 ldap_memfree(srv_dn_utf8);
2710 ldap_memfree(srv_cn_utf8);
2711 ads_destroy(&ads);
2712 SAFE_FREE(srv_dn);
2713 return WERR_SERVER_UNAVAILABLE;
2716 ldap_memfree(srv_dn_utf8);
2717 ldap_memfree(srv_cn_utf8);
2719 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2720 printer->info_2->sharename, srv_dn);
2722 SAFE_FREE(srv_dn);
2723 SAFE_FREE(srv_cn_0);
2725 /* publish it */
2726 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2727 if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2728 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2730 /* retreive the guid and store it locally */
2731 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2732 ads_pull_guid(ads, res, &guid);
2733 ads_msgfree(ads, res);
2734 store_printer_guid(printer->info_2, guid);
2735 win_rc = mod_a_printer(*printer, 2);
2738 SAFE_FREE(prt_dn);
2739 ads_destroy(&ads);
2741 return WERR_OK;
2744 WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2746 ADS_STATUS ads_rc;
2747 ADS_STRUCT *ads;
2748 void *res;
2749 char *prt_dn = NULL;
2750 WERROR win_rc;
2752 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2753 win_rc = mod_a_printer(*printer, 2);
2754 if (!W_ERROR_IS_OK(win_rc)) {
2755 DEBUG(3, ("err %d saving data\n",
2756 W_ERROR_V(win_rc)));
2757 return win_rc;
2760 ads = ads_init(NULL, NULL, NULL);
2761 if (!ads) {
2762 DEBUG(3, ("ads_init() failed\n"));
2763 return WERR_SERVER_UNAVAILABLE;
2765 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2766 SAFE_FREE(ads->auth.password);
2767 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2768 NULL, NULL);
2770 /* ads_connect() will find the DC for us */
2771 ads_rc = ads_connect(ads);
2772 if (!ADS_ERR_OK(ads_rc)) {
2773 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2774 ads_destroy(&ads);
2775 return WERR_ACCESS_DENIED;
2778 /* remove the printer from the directory */
2779 ads_rc = ads_find_printer_on_server(ads, &res,
2780 printer->info_2->sharename, global_myname());
2781 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2782 prt_dn = ads_get_dn(ads, res);
2783 ads_msgfree(ads, res);
2784 ads_rc = ads_del_dn(ads, prt_dn);
2785 ads_memfree(ads, prt_dn);
2788 ads_destroy(&ads);
2789 return WERR_OK;
2792 /****************************************************************************
2793 * Publish a printer in the directory
2795 * @param snum describing printer service
2796 * @return WERROR indicating status of publishing
2797 ***************************************************************************/
2799 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2801 NT_PRINTER_INFO_LEVEL *printer = NULL;
2802 WERROR win_rc;
2804 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2805 if (!W_ERROR_IS_OK(win_rc))
2806 return win_rc;
2808 switch(action) {
2809 case SPOOL_DS_PUBLISH:
2810 case SPOOL_DS_UPDATE:
2811 win_rc = publish_it(printer);
2812 break;
2813 case SPOOL_DS_UNPUBLISH:
2814 win_rc = unpublish_it(printer);
2815 break;
2816 default:
2817 win_rc = WERR_NOT_SUPPORTED;
2821 free_a_printer(&printer, 2);
2822 return win_rc;
2825 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
2826 struct uuid *guid)
2828 NT_PRINTER_INFO_LEVEL *printer = NULL;
2829 REGVAL_CTR *ctr;
2830 REGISTRY_VALUE *guid_val;
2831 WERROR win_rc;
2832 int i;
2835 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2836 if (!W_ERROR_IS_OK(win_rc))
2837 return False;
2839 if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2840 return False;
2842 if ((i = lookup_printerkey(&printer->info_2->data,
2843 SPOOL_DSSPOOLER_KEY)) < 0)
2844 return False;
2846 if (!(ctr = &printer->info_2->data.keys[i].values)) {
2847 return False;
2850 if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2851 return False;
2854 if (regval_size(guid_val) == sizeof(struct uuid))
2855 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
2857 return True;
2860 #else
2861 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2863 return WERR_OK;
2865 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
2866 struct uuid *guid)
2868 return False;
2870 #endif
2871 /****************************************************************************
2872 ***************************************************************************/
2874 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2876 NT_PRINTER_DATA *data;
2877 int i;
2878 int removed_keys = 0;
2879 int empty_slot;
2881 data = &p2->data;
2882 empty_slot = data->num_keys;
2884 if ( !key )
2885 return WERR_INVALID_PARAM;
2887 /* remove all keys */
2889 if ( !strlen(key) ) {
2890 for ( i=0; i<data->num_keys; i++ ) {
2891 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2892 data->keys[i].name));
2894 SAFE_FREE( data->keys[i].name );
2895 regval_ctr_destroy( &data->keys[i].values );
2898 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2899 p2->printername ));
2901 SAFE_FREE( data->keys );
2902 ZERO_STRUCTP( data );
2904 return WERR_OK;
2907 /* remove a specific key (and all subkeys) */
2909 for ( i=0; i<data->num_keys; i++ ) {
2910 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2911 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2912 data->keys[i].name));
2914 SAFE_FREE( data->keys[i].name );
2915 regval_ctr_destroy( &data->keys[i].values );
2917 /* mark the slot as empty */
2919 ZERO_STRUCTP( &data->keys[i] );
2923 /* find the first empty slot */
2925 for ( i=0; i<data->num_keys; i++ ) {
2926 if ( !data->keys[i].name ) {
2927 empty_slot = i;
2928 removed_keys++;
2929 break;
2933 if ( i == data->num_keys )
2934 /* nothing was removed */
2935 return WERR_INVALID_PARAM;
2937 /* move everything down */
2939 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2940 if ( data->keys[i].name ) {
2941 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2942 ZERO_STRUCTP( &data->keys[i] );
2943 empty_slot++;
2944 removed_keys++;
2948 /* update count */
2950 data->num_keys -= removed_keys;
2952 /* sanity check to see if anything is left */
2954 if ( !data->num_keys ) {
2955 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2957 SAFE_FREE( data->keys );
2958 ZERO_STRUCTP( data );
2961 return WERR_OK;
2964 /****************************************************************************
2965 ***************************************************************************/
2967 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2969 WERROR result = WERR_OK;
2970 int key_index;
2972 /* we must have names on non-zero length */
2974 if ( !key || !*key|| !value || !*value )
2975 return WERR_INVALID_NAME;
2977 /* find the printer key first */
2979 key_index = lookup_printerkey( &p2->data, key );
2980 if ( key_index == -1 )
2981 return WERR_OK;
2983 /* make sure the value exists so we can return the correct error code */
2985 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
2986 return WERR_BADFILE;
2988 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2990 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2991 key, value ));
2993 return result;
2996 /****************************************************************************
2997 ***************************************************************************/
2999 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3000 uint32 type, uint8 *data, int real_len )
3002 WERROR result = WERR_OK;
3003 int key_index;
3005 /* we must have names on non-zero length */
3007 if ( !key || !*key|| !value || !*value )
3008 return WERR_INVALID_NAME;
3010 /* find the printer key first */
3012 key_index = lookup_printerkey( &p2->data, key );
3013 if ( key_index == -1 )
3014 key_index = add_new_printer_key( &p2->data, key );
3016 if ( key_index == -1 )
3017 return WERR_NOMEM;
3019 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3020 type, (const char *)data, real_len );
3022 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3023 key, value, type, real_len ));
3025 return result;
3028 /****************************************************************************
3029 ***************************************************************************/
3031 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3033 int key_index;
3035 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3036 return NULL;
3038 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3039 key, value ));
3041 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3044 /****************************************************************************
3045 Unpack a list of registry values frem the TDB
3046 ***************************************************************************/
3048 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3050 int len = 0;
3051 uint32 type;
3052 pstring string, valuename, keyname;
3053 char *str;
3054 int size;
3055 uint8 *data_p;
3056 REGISTRY_VALUE *regval_p;
3057 int key_index;
3059 /* add the "PrinterDriverData" key first for performance reasons */
3061 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3063 /* loop and unpack the rest of the registry values */
3065 while ( True ) {
3067 /* check to see if there are any more registry values */
3069 regval_p = NULL;
3070 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3071 if ( !regval_p )
3072 break;
3074 /* unpack the next regval */
3076 len += tdb_unpack(buf+len, buflen-len, "fdB",
3077 string,
3078 &type,
3079 &size,
3080 &data_p);
3083 * break of the keyname from the value name.
3084 * Valuenames can have embedded '\'s so be careful.
3085 * only support one level of keys. See the
3086 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3087 * -- jerry
3090 str = strchr_m( string, '\\');
3092 /* Put in "PrinterDriverData" is no key specified */
3094 if ( !str ) {
3095 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3096 pstrcpy( valuename, string );
3098 else {
3099 *str = '\0';
3100 pstrcpy( keyname, string );
3101 pstrcpy( valuename, str+1 );
3104 /* see if we need a new key */
3106 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3107 key_index = add_new_printer_key( printer_data, keyname );
3109 if ( key_index == -1 ) {
3110 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3111 keyname));
3112 break;
3115 /* add the new value */
3117 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3119 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3121 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3124 return len;
3127 /****************************************************************************
3128 ***************************************************************************/
3130 static void map_to_os2_driver(fstring drivername)
3132 static BOOL initialised=False;
3133 static fstring last_from,last_to;
3134 char *mapfile = lp_os2_driver_map();
3135 char **lines = NULL;
3136 int numlines = 0;
3137 int i;
3139 if (!strlen(drivername))
3140 return;
3142 if (!*mapfile)
3143 return;
3145 if (!initialised) {
3146 *last_from = *last_to = 0;
3147 initialised = True;
3150 if (strequal(drivername,last_from)) {
3151 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3152 fstrcpy(drivername,last_to);
3153 return;
3156 lines = file_lines_load(mapfile, &numlines);
3157 if (numlines == 0) {
3158 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3159 return;
3162 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3164 for( i = 0; i < numlines; i++) {
3165 char *nt_name = lines[i];
3166 char *os2_name = strchr(nt_name,'=');
3168 if (!os2_name)
3169 continue;
3171 *os2_name++ = 0;
3173 while (isspace(*nt_name))
3174 nt_name++;
3176 if (!*nt_name || strchr("#;",*nt_name))
3177 continue;
3180 int l = strlen(nt_name);
3181 while (l && isspace(nt_name[l-1])) {
3182 nt_name[l-1] = 0;
3183 l--;
3187 while (isspace(*os2_name))
3188 os2_name++;
3191 int l = strlen(os2_name);
3192 while (l && isspace(os2_name[l-1])) {
3193 os2_name[l-1] = 0;
3194 l--;
3198 if (strequal(nt_name,drivername)) {
3199 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3200 fstrcpy(last_from,drivername);
3201 fstrcpy(last_to,os2_name);
3202 fstrcpy(drivername,os2_name);
3203 file_lines_free(lines);
3204 return;
3208 file_lines_free(lines);
3211 /****************************************************************************
3212 Get a default printer info 2 struct.
3213 ****************************************************************************/
3214 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3216 int snum;
3217 NT_PRINTER_INFO_LEVEL_2 info;
3219 ZERO_STRUCT(info);
3221 snum = lp_servicenumber(sharename);
3223 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3224 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3225 get_called_name(), sharename);
3226 fstrcpy(info.sharename, sharename);
3227 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3229 /* by setting the driver name to an empty string, a local NT admin
3230 can now run the **local** APW to install a local printer driver
3231 for a Samba shared printer in 2.2. Without this, drivers **must** be
3232 installed on the Samba server for NT clients --jerry */
3233 #if 0 /* JERRY --do not uncomment-- */
3234 if (!*info.drivername)
3235 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3236 #endif
3239 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3241 pstrcpy(info.comment, "");
3242 fstrcpy(info.printprocessor, "winprint");
3243 fstrcpy(info.datatype, "RAW");
3245 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3247 info.starttime = 0; /* Minutes since 12:00am GMT */
3248 info.untiltime = 0; /* Minutes since 12:00am GMT */
3249 info.priority = 1;
3250 info.default_priority = 1;
3251 info.setuptime = (uint32)time(NULL);
3254 * I changed this as I think it is better to have a generic
3255 * DEVMODE than to crash Win2k explorer.exe --jerry
3256 * See the HP Deskjet 990c Win2k drivers for an example.
3258 * However the default devmode appears to cause problems
3259 * with the HP CLJ 8500 PCL driver. Hence the addition of
3260 * the "default devmode" parameter --jerry 22/01/2002
3263 if (lp_default_devmode(snum)) {
3264 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3265 goto fail;
3267 else {
3268 info.devmode = NULL;
3271 /* This will get the current RPC talloc context, but we should be
3272 passing this as a parameter... fixme... JRA ! */
3274 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3275 goto fail;
3277 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3278 if (! *info_ptr) {
3279 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3280 goto fail;
3283 return WERR_OK;
3285 fail:
3286 if (info.devmode)
3287 free_nt_devicemode(&info.devmode);
3288 return WERR_ACCESS_DENIED;
3291 /****************************************************************************
3292 ****************************************************************************/
3293 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3295 pstring key;
3296 NT_PRINTER_INFO_LEVEL_2 info;
3297 int len = 0;
3298 TDB_DATA kbuf, dbuf;
3299 fstring printername;
3300 char adevice[MAXDEVICENAME];
3302 ZERO_STRUCT(info);
3304 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3306 kbuf.dptr = key;
3307 kbuf.dsize = strlen(key)+1;
3309 dbuf = tdb_fetch(tdb_printers, kbuf);
3310 if (!dbuf.dptr)
3311 return get_a_printer_2_default(info_ptr, sharename);
3313 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3314 &info.attributes,
3315 &info.priority,
3316 &info.default_priority,
3317 &info.starttime,
3318 &info.untiltime,
3319 &info.status,
3320 &info.cjobs,
3321 &info.averageppm,
3322 &info.changeid,
3323 &info.c_setprinter,
3324 &info.setuptime,
3325 info.servername,
3326 info.printername,
3327 info.sharename,
3328 info.portname,
3329 info.drivername,
3330 info.comment,
3331 info.location,
3332 info.sepfile,
3333 info.printprocessor,
3334 info.datatype,
3335 info.parameters);
3337 /* Samba has to have shared raw drivers. */
3338 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3339 info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3341 /* Restore the stripped strings. */
3342 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3343 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3344 info.printername);
3345 fstrcpy(info.printername, printername);
3347 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3350 * Some client drivers freak out if there is a NULL devmode
3351 * (probably the driver is not checking before accessing
3352 * the devmode pointer) --jerry
3354 * See comments in get_a_printer_2_default()
3357 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3358 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3359 printername));
3360 info.devmode = construct_nt_devicemode(printername);
3363 safe_strcpy(adevice, info.printername, sizeof(adevice)-1);
3364 if (info.devmode) {
3365 fstrcpy(info.devmode->devicename, adevice);
3368 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3370 /* This will get the current RPC talloc context, but we should be
3371 passing this as a parameter... fixme... JRA ! */
3373 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3375 /* Fix for OS/2 drivers. */
3377 if (get_remote_arch() == RA_OS2)
3378 map_to_os2_driver(info.drivername);
3380 SAFE_FREE(dbuf.dptr);
3381 *info_ptr=memdup(&info, sizeof(info));
3383 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3384 sharename, info.printername, info.drivername));
3386 return WERR_OK;
3389 /****************************************************************************
3390 Debugging function, dump at level 6 the struct in the logs.
3391 ****************************************************************************/
3392 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3394 uint32 result;
3395 NT_PRINTER_INFO_LEVEL_2 *info2;
3397 DEBUG(106,("Dumping printer at level [%d]\n", level));
3399 switch (level) {
3400 case 2:
3402 if (printer.info_2 == NULL)
3403 result=5;
3404 else
3406 info2=printer.info_2;
3408 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3409 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3410 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3411 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3412 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3413 DEBUGADD(106,("status:[%d]\n", info2->status));
3414 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3415 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3416 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3417 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3418 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3420 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3421 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3422 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3423 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3424 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3425 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3426 DEBUGADD(106,("location:[%s]\n", info2->location));
3427 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3428 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3429 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3430 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3431 result=0;
3433 break;
3435 default:
3436 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3437 result=1;
3438 break;
3441 return result;
3444 /****************************************************************************
3445 Update the changeid time.
3446 This is SO NASTY as some drivers need this to change, others need it
3447 static. This value will change every second, and I must hope that this
3448 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3449 UTAH ! JRA.
3450 ****************************************************************************/
3452 static uint32 rev_changeid(void)
3454 struct timeval tv;
3456 get_process_uptime(&tv);
3458 #if 1 /* JERRY */
3459 /* Return changeid as msec since spooler restart */
3460 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3461 #else
3463 * This setting seems to work well but is too untested
3464 * to replace the above calculation. Left in for experiementation
3465 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3467 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3468 #endif
3471 /********************************************************************
3472 Send a message to all smbds about the printer that just changed
3473 ********************************************************************/
3475 static BOOL send_printer_mod_msg( char* printername )
3477 int len = strlen(printername);
3479 if (!len)
3480 return False;
3482 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3483 printername));
3485 /* spam everyone that we just changed this printer */
3487 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3489 return True;
3493 * The function below are the high level ones.
3494 * only those ones must be called from the spoolss code.
3495 * JFM.
3498 /****************************************************************************
3499 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3500 ****************************************************************************/
3502 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3504 WERROR result;
3506 dump_a_printer(printer, level);
3509 * invalidate cache for all open handles to this printer.
3510 * cache for a given handle will be updated on the next
3511 * get_a_printer()
3514 invalidate_printer_hnd_cache( printer.info_2->sharename );
3515 send_printer_mod_msg( printer.info_2->sharename );
3517 switch (level) {
3518 case 2:
3521 * Update the changestamp. Emperical tests show that the
3522 * ChangeID is always updated,but c_setprinter is
3523 * global spooler variable (not per printer).
3526 /* ChangeID **must** be increasing over the lifetime
3527 of client's spoolss service in order for the
3528 client's cache to show updates */
3530 printer.info_2->changeid = rev_changeid();
3533 * Because one day someone will ask:
3534 * NT->NT An admin connection to a remote
3535 * printer show changes imeediately in
3536 * the properities dialog
3538 * A non-admin connection will only show the
3539 * changes after viewing the properites page
3540 * 2 times. Seems to be related to a
3541 * race condition in the client between the spooler
3542 * updating the local cache and the Explorer.exe GUI
3543 * actually displaying the properties.
3545 * This is fixed in Win2k. admin/non-admin
3546 * connections both display changes immediately.
3548 * 14/12/01 --jerry
3551 result=update_a_printer_2(printer.info_2);
3553 break;
3555 default:
3556 result=WERR_UNKNOWN_LEVEL;
3557 break;
3560 return result;
3563 /****************************************************************************
3564 Initialize printer devmode & data with previously saved driver init values.
3565 ****************************************************************************/
3567 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3569 int len = 0;
3570 pstring key;
3571 TDB_DATA kbuf, dbuf;
3572 NT_PRINTER_INFO_LEVEL_2 info;
3575 ZERO_STRUCT(info);
3578 * Delete any printer data 'values' already set. When called for driver
3579 * replace, there will generally be some, but during an add printer, there
3580 * should not be any (if there are delete them).
3583 delete_all_printer_data( info_ptr, "" );
3585 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3587 kbuf.dptr = key;
3588 kbuf.dsize = strlen(key)+1;
3590 dbuf = tdb_fetch(tdb_drivers, kbuf);
3591 if (!dbuf.dptr) {
3593 * When changing to a driver that has no init info in the tdb, remove
3594 * the previous drivers init info and leave the new on blank.
3596 free_nt_devicemode(&info_ptr->devmode);
3597 return False;
3601 * Get the saved DEVMODE..
3604 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3607 * The saved DEVMODE contains the devicename from the printer used during
3608 * the initialization save. Change it to reflect the new printer.
3611 if ( info.devmode ) {
3612 ZERO_STRUCT(info.devmode->devicename);
3613 fstrcpy(info.devmode->devicename, info_ptr->printername);
3617 * NT/2k does not change out the entire DeviceMode of a printer
3618 * when changing the driver. Only the driverextra, private, &
3619 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3621 * Later examination revealed that Windows NT/2k does reset the
3622 * the printer's device mode, bit **only** when you change a
3623 * property of the device mode such as the page orientation.
3624 * --jerry
3628 /* Bind the saved DEVMODE to the new the printer */
3630 free_nt_devicemode(&info_ptr->devmode);
3631 info_ptr->devmode = info.devmode;
3633 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3634 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3636 /* Add the printer data 'values' to the new printer */
3638 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3641 SAFE_FREE(dbuf.dptr);
3643 return True;
3646 /****************************************************************************
3647 Initialize printer devmode & data with previously saved driver init values.
3648 When a printer is created using AddPrinter, the drivername bound to the
3649 printer is used to lookup previously saved driver initialization info, which
3650 is bound to the new printer.
3651 ****************************************************************************/
3653 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3655 BOOL result = False;
3657 switch (level) {
3658 case 2:
3659 result = set_driver_init_2(printer->info_2);
3660 break;
3662 default:
3663 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3664 level));
3665 break;
3668 return result;
3671 /****************************************************************************
3672 Delete driver init data stored for a specified driver
3673 ****************************************************************************/
3675 BOOL del_driver_init(char *drivername)
3677 pstring key;
3678 TDB_DATA kbuf;
3680 if (!drivername || !*drivername) {
3681 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3682 return False;
3685 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3687 kbuf.dptr = key;
3688 kbuf.dsize = strlen(key)+1;
3690 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3692 return (tdb_delete(tdb_drivers, kbuf) == 0);
3695 /****************************************************************************
3696 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3697 in the tdb. Note: this is different from the driver entry and the printer
3698 entry. There should be a single driver init entry for each driver regardless
3699 of whether it was installed from NT or 2K. Technically, they should be
3700 different, but they work out to the same struct.
3701 ****************************************************************************/
3703 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3705 pstring key;
3706 char *buf;
3707 int buflen, len, ret;
3708 TDB_DATA kbuf, dbuf;
3710 buf = NULL;
3711 buflen = 0;
3713 again:
3714 len = 0;
3715 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3717 len += pack_values( &info->data, buf+len, buflen-len );
3719 if (buflen != len) {
3720 char *tb;
3722 tb = (char *)Realloc(buf, len);
3723 if (!tb) {
3724 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3725 ret = -1;
3726 goto done;
3728 else
3729 buf = tb;
3730 buflen = len;
3731 goto again;
3734 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3736 kbuf.dptr = key;
3737 kbuf.dsize = strlen(key)+1;
3738 dbuf.dptr = buf;
3739 dbuf.dsize = len;
3741 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3743 done:
3744 if (ret == -1)
3745 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3747 SAFE_FREE(buf);
3749 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3750 info->sharename, info->drivername));
3752 return ret;
3755 /****************************************************************************
3756 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3757 ****************************************************************************/
3759 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3761 uint32 result;
3763 dump_a_printer(printer, level);
3765 switch (level) {
3766 case 2:
3767 result = update_driver_init_2(printer.info_2);
3768 break;
3769 default:
3770 result = 1;
3771 break;
3774 return result;
3777 /****************************************************************************
3778 Convert the printer data value, a REG_BINARY array, into an initialization
3779 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3780 got to keep the endians happy :).
3781 ****************************************************************************/
3783 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3785 BOOL result = False;
3786 prs_struct ps;
3787 DEVICEMODE devmode;
3789 ZERO_STRUCT(devmode);
3791 prs_init(&ps, 0, ctx, UNMARSHALL);
3792 ps.data_p = (char *)data;
3793 ps.buffer_size = data_len;
3795 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3796 result = convert_devicemode("", &devmode, &nt_devmode);
3797 else
3798 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3800 return result;
3803 /****************************************************************************
3804 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3806 1. Use the driver's config DLL to this UNC printername and:
3807 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3808 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3809 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3811 The last step triggers saving the "driver initialization" information for
3812 this printer into the tdb. Later, new printers that use this driver will
3813 have this initialization information bound to them. This simulates the
3814 driver initialization, as if it had run on the Samba server (as it would
3815 have done on NT).
3817 The Win32 client side code requirement sucks! But until we can run arbitrary
3818 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3820 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3821 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3822 about it and you will realize why. JRR 010720
3823 ****************************************************************************/
3825 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3827 WERROR status = WERR_OK;
3828 TALLOC_CTX *ctx = NULL;
3829 NT_DEVICEMODE *nt_devmode = NULL;
3830 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3833 * When the DEVMODE is already set on the printer, don't try to unpack it.
3835 DEBUG(8,("save_driver_init_2: Enter...\n"));
3837 if ( !printer->info_2->devmode && data_len ) {
3839 * Set devmode on printer info, so entire printer initialization can be
3840 * saved to tdb.
3843 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3844 return WERR_NOMEM;
3846 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3847 status = WERR_NOMEM;
3848 goto done;
3851 ZERO_STRUCTP(nt_devmode);
3854 * The DEVMODE is held in the 'data' component of the param in raw binary.
3855 * Convert it to to a devmode structure
3857 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3858 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3859 status = WERR_INVALID_PARAM;
3860 goto done;
3863 printer->info_2->devmode = nt_devmode;
3867 * Pack up and add (or update) the DEVMODE and any current printer data to
3868 * a 'driver init' element in the tdb
3872 if ( update_driver_init(*printer, 2) != 0 ) {
3873 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3874 status = WERR_NOMEM;
3875 goto done;
3879 * If driver initialization info was successfully saved, set the current
3880 * printer to match it. This allows initialization of the current printer
3881 * as well as the driver.
3883 status = mod_a_printer(*printer, 2);
3884 if (!W_ERROR_IS_OK(status)) {
3885 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3886 printer->info_2->printername));
3889 done:
3890 talloc_destroy(ctx);
3891 free_nt_devicemode( &nt_devmode );
3893 printer->info_2->devmode = tmp_devmode;
3895 return status;
3898 /****************************************************************************
3899 Update the driver init info (DEVMODE and specifics) for a printer
3900 ****************************************************************************/
3902 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3904 WERROR status = WERR_OK;
3906 switch (level) {
3907 case 2:
3908 status = save_driver_init_2( printer, data, data_len );
3909 break;
3910 default:
3911 status = WERR_UNKNOWN_LEVEL;
3912 break;
3915 return status;
3918 /****************************************************************************
3919 Deep copy a NT_PRINTER_DATA
3920 ****************************************************************************/
3922 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3924 int i, j, num_vals, new_key_index;
3925 REGVAL_CTR *src_key, *dst_key;
3927 if ( !dst || !src )
3928 return NT_STATUS_NO_MEMORY;
3930 for ( i=0; i<src->num_keys; i++ ) {
3932 /* create a new instance of the printerkey in the destination
3933 printer_data object */
3935 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3936 dst_key = &dst->keys[new_key_index].values;
3938 src_key = &src->keys[i].values;
3939 num_vals = regval_ctr_numvals( src_key );
3941 /* dup the printer entire printer key */
3943 for ( j=0; j<num_vals; j++ ) {
3944 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3948 return NT_STATUS_OK;
3951 /****************************************************************************
3952 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3953 Caller must free.
3954 ****************************************************************************/
3956 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3958 NT_PRINTER_INFO_LEVEL_2 *copy;
3960 if ( !printer )
3961 return NULL;
3963 if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3964 return NULL;
3966 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3968 /* malloc()'d members copied here */
3970 copy->devmode = dup_nt_devicemode( printer->devmode );
3972 ZERO_STRUCT( copy->data );
3973 copy_printer_data( &copy->data, &printer->data );
3975 /* this is talloc()'d; very ugly that we have a structure that
3976 is half malloc()'d and half talloc()'d but that is the way
3977 that the PRINTER_INFO stuff is written right now. --jerry */
3979 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3981 return copy;
3984 /****************************************************************************
3985 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3987 Previously the code had a memory allocation problem because it always
3988 used the TALLOC_CTX from the Printer_entry*. This context lasts
3989 as a long as the original handle is open. So if the client made a lot
3990 of getprinter[data]() calls, the memory usage would climb. Now we use
3991 a short lived TALLOC_CTX for printer_info_2 objects returned. We
3992 still use the Printer_entry->ctx for maintaining the cache copy though
3993 since that object must live as long as the handle by definition.
3994 --jerry
3996 ****************************************************************************/
3998 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
3999 const char *sharename)
4001 WERROR result;
4002 NT_PRINTER_INFO_LEVEL *printer = NULL;
4004 *pp_printer = NULL;
4006 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4008 switch (level) {
4009 case 2:
4010 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4011 DEBUG(0,("get_a_printer: malloc fail.\n"));
4012 return WERR_NOMEM;
4014 ZERO_STRUCTP(printer);
4017 * check for cache first. A Printer handle cannot changed
4018 * to another printer object so we only check that the printer
4019 * is actually for a printer and that the printer_info pointer
4020 * is valid
4022 if ( print_hnd
4023 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
4024 && print_hnd->printer_info )
4026 /* get_talloc_ctx() works here because we need a short
4027 lived talloc context */
4029 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
4031 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4033 SAFE_FREE(printer);
4034 return WERR_NOMEM;
4037 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4039 *pp_printer = printer;
4040 result = WERR_OK;
4042 break;
4045 /* no cache for this handle; see if we can match one from another handle.
4046 Make sure to use a short lived talloc ctx */
4048 if ( print_hnd )
4049 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, sharename);
4051 /* fail to disk if we don't have it with any open handle */
4053 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4054 result = get_a_printer_2(&printer->info_2, sharename);
4056 /* we have a new printer now. Save it with this handle */
4058 if ( W_ERROR_IS_OK(result) ) {
4059 dump_a_printer(*printer, level);
4061 /* save a copy in cache */
4062 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4063 if ( !print_hnd->printer_info )
4064 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
4066 if ( print_hnd->printer_info ) {
4067 /* make sure to use the handle's talloc ctx here since
4068 the printer_2 object must last until the handle is closed */
4070 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4072 /* don't fail the lookup just because the cache update failed */
4073 if ( !print_hnd->printer_info->info_2 )
4074 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4077 *pp_printer = printer;
4079 else
4080 SAFE_FREE(printer);
4082 break;
4084 default:
4085 result=WERR_UNKNOWN_LEVEL;
4086 break;
4089 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4091 return result;
4094 /****************************************************************************
4095 Deletes a NT_PRINTER_INFO_LEVEL struct.
4096 ****************************************************************************/
4098 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4100 uint32 result;
4101 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4103 DEBUG(104,("freeing a printer at level [%d]\n", level));
4105 if (printer == NULL)
4106 return 0;
4108 switch (level) {
4109 case 2:
4110 if (printer->info_2 != NULL) {
4111 free_nt_printer_info_level_2(&printer->info_2);
4112 result=0;
4113 } else
4114 result=4;
4115 break;
4117 default:
4118 result=1;
4119 break;
4122 SAFE_FREE(*pp_printer);
4123 return result;
4126 /****************************************************************************
4127 ****************************************************************************/
4128 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4130 uint32 result;
4131 DEBUG(104,("adding a printer at level [%d]\n", level));
4132 dump_a_printer_driver(driver, level);
4134 switch (level) {
4135 case 3:
4136 result=add_a_printer_driver_3(driver.info_3);
4137 break;
4139 case 6:
4140 result=add_a_printer_driver_6(driver.info_6);
4141 break;
4143 default:
4144 result=1;
4145 break;
4148 return result;
4150 /****************************************************************************
4151 ****************************************************************************/
4153 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4154 fstring drivername, const char *architecture, uint32 version)
4156 WERROR result;
4158 switch (level) {
4159 case 3:
4160 /* Sometime we just want any version of the driver */
4162 if ( version == DRIVER_ANY_VERSION ) {
4163 /* look for Win2k first and then for NT4 */
4164 result = get_a_printer_driver_3(&driver->info_3, drivername,
4165 architecture, 3);
4167 if ( !W_ERROR_IS_OK(result) ) {
4168 result = get_a_printer_driver_3( &driver->info_3,
4169 drivername, architecture, 2 );
4171 } else {
4172 result = get_a_printer_driver_3(&driver->info_3, drivername,
4173 architecture, version);
4175 break;
4177 default:
4178 result=W_ERROR(1);
4179 break;
4182 if (W_ERROR_IS_OK(result))
4183 dump_a_printer_driver(*driver, level);
4185 return result;
4188 /****************************************************************************
4189 ****************************************************************************/
4190 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4192 uint32 result;
4194 switch (level) {
4195 case 3:
4197 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4198 if (driver.info_3 != NULL)
4200 info3=driver.info_3;
4201 SAFE_FREE(info3->dependentfiles);
4202 ZERO_STRUCTP(info3);
4203 SAFE_FREE(info3);
4204 result=0;
4205 } else {
4206 result=4;
4208 break;
4210 case 6:
4212 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4213 if (driver.info_6 != NULL) {
4214 info6=driver.info_6;
4215 SAFE_FREE(info6->dependentfiles);
4216 SAFE_FREE(info6->previousnames);
4217 ZERO_STRUCTP(info6);
4218 SAFE_FREE(info6);
4219 result=0;
4220 } else {
4221 result=4;
4223 break;
4225 default:
4226 result=1;
4227 break;
4229 return result;
4233 /****************************************************************************
4234 Determine whether or not a particular driver is currently assigned
4235 to a printer
4236 ****************************************************************************/
4238 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4240 int snum;
4241 int n_services = lp_numservices();
4242 NT_PRINTER_INFO_LEVEL *printer = NULL;
4244 if ( !info_3 )
4245 return False;
4247 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4249 /* loop through the printers.tdb and check for the drivername */
4251 for (snum=0; snum<n_services; snum++) {
4252 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4253 continue;
4255 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4256 continue;
4258 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4259 free_a_printer( &printer, 2 );
4260 return True;
4263 free_a_printer( &printer, 2 );
4266 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4268 /* report that the driver is not in use by default */
4270 return False;
4274 /**********************************************************************
4275 Check to see if a ogiven file is in use by *info
4276 *********************************************************************/
4278 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4280 int i = 0;
4282 if ( !info )
4283 return False;
4285 if ( strequal(file, info->driverpath) )
4286 return True;
4288 if ( strequal(file, info->datafile) )
4289 return True;
4291 if ( strequal(file, info->configfile) )
4292 return True;
4294 if ( strequal(file, info->helpfile) )
4295 return True;
4297 /* see of there are any dependent files to examine */
4299 if ( !info->dependentfiles )
4300 return False;
4302 while ( *info->dependentfiles[i] ) {
4303 if ( strequal(file, info->dependentfiles[i]) )
4304 return True;
4305 i++;
4308 return False;
4312 /**********************************************************************
4313 Utility function to remove the dependent file pointed to by the
4314 input parameter from the list
4315 *********************************************************************/
4317 static void trim_dependent_file( fstring files[], int idx )
4320 /* bump everything down a slot */
4322 while( *files[idx+1] ) {
4323 fstrcpy( files[idx], files[idx+1] );
4324 idx++;
4327 *files[idx] = '\0';
4329 return;
4332 /**********************************************************************
4333 Check if any of the files used by src are also used by drv
4334 *********************************************************************/
4336 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4337 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4339 BOOL in_use = False;
4340 int i = 0;
4342 if ( !src || !drv )
4343 return False;
4345 /* check each file. Remove it from the src structure if it overlaps */
4347 if ( drv_file_in_use(src->driverpath, drv) ) {
4348 in_use = True;
4349 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4350 fstrcpy( src->driverpath, "" );
4353 if ( drv_file_in_use(src->datafile, drv) ) {
4354 in_use = True;
4355 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4356 fstrcpy( src->datafile, "" );
4359 if ( drv_file_in_use(src->configfile, drv) ) {
4360 in_use = True;
4361 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4362 fstrcpy( src->configfile, "" );
4365 if ( drv_file_in_use(src->helpfile, drv) ) {
4366 in_use = True;
4367 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4368 fstrcpy( src->helpfile, "" );
4371 /* are there any dependentfiles to examine? */
4373 if ( !src->dependentfiles )
4374 return in_use;
4376 while ( *src->dependentfiles[i] ) {
4377 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4378 in_use = True;
4379 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4380 trim_dependent_file( src->dependentfiles, i );
4381 } else
4382 i++;
4385 return in_use;
4388 /****************************************************************************
4389 Determine whether or not a particular driver files are currently being
4390 used by any other driver.
4392 Return value is True if any files were in use by other drivers
4393 and False otherwise.
4395 Upon return, *info has been modified to only contain the driver files
4396 which are not in use
4397 ****************************************************************************/
4399 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4401 int i;
4402 int ndrivers;
4403 uint32 version;
4404 fstring *list = NULL;
4405 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4407 if ( !info )
4408 return False;
4410 version = info->cversion;
4412 /* loop over all driver versions */
4414 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4416 /* get the list of drivers */
4418 list = NULL;
4419 ndrivers = get_ntdrivers(&list, info->environment, version);
4421 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4422 ndrivers, info->environment, version));
4424 /* check each driver for overlap in files */
4426 for (i=0; i<ndrivers; i++) {
4427 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4429 ZERO_STRUCT(driver);
4431 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4432 SAFE_FREE(list);
4433 return True;
4436 /* check if d2 uses any files from d1 */
4437 /* only if this is a different driver than the one being deleted */
4439 if ( !strequal(info->name, driver.info_3->name) ) {
4440 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4441 free_a_printer_driver(driver, 3);
4442 SAFE_FREE( list );
4443 return True;
4447 free_a_printer_driver(driver, 3);
4450 SAFE_FREE(list);
4452 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4454 driver.info_3 = info;
4456 if ( DEBUGLEVEL >= 20 )
4457 dump_a_printer_driver( driver, 3 );
4459 return False;
4462 /****************************************************************************
4463 Actually delete the driver files. Make sure that
4464 printer_driver_files_in_use() return False before calling
4465 this.
4466 ****************************************************************************/
4468 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4470 int i = 0;
4471 char *s;
4472 connection_struct *conn;
4473 DATA_BLOB null_pw;
4474 NTSTATUS nt_status;
4475 fstring res_type;
4476 BOOL bad_path;
4477 SMB_STRUCT_STAT st;
4479 if ( !info_3 )
4480 return False;
4482 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4485 * Connect to the print$ share under the same account as the
4486 * user connected to the rpc pipe. Note we must be root to
4487 * do this.
4490 null_pw = data_blob( NULL, 0 );
4491 fstrcpy(res_type, "A:");
4492 become_root();
4493 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4494 unbecome_root();
4496 if ( !conn ) {
4497 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4498 return False;
4501 /* Save who we are - we are temporarily becoming the connection user. */
4503 if ( !become_user(conn, conn->vuid) ) {
4504 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4505 return False;
4508 /* now delete the files; must strip the '\print$' string from
4509 fron of path */
4511 if ( *info_3->driverpath ) {
4512 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4513 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4514 DEBUG(10,("deleting driverfile [%s]\n", s));
4515 unlink_internals(conn, 0, s);
4519 if ( *info_3->configfile ) {
4520 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4521 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4522 DEBUG(10,("deleting configfile [%s]\n", s));
4523 unlink_internals(conn, 0, s);
4527 if ( *info_3->datafile ) {
4528 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4529 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4530 DEBUG(10,("deleting datafile [%s]\n", s));
4531 unlink_internals(conn, 0, s);
4535 if ( *info_3->helpfile ) {
4536 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4537 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4538 DEBUG(10,("deleting helpfile [%s]\n", s));
4539 unlink_internals(conn, 0, s);
4543 /* check if we are done removing files */
4545 if ( info_3->dependentfiles ) {
4546 while ( *info_3->dependentfiles[i] ) {
4547 char *file;
4549 /* bypass the "\print$" portion of the path */
4551 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4552 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4553 DEBUG(10,("deleting dependent file [%s]\n", file));
4554 unlink_internals(conn, 0, file );
4557 i++;
4561 unbecome_user();
4563 return True;
4566 /****************************************************************************
4567 Remove a printer driver from the TDB. This assumes that the the driver was
4568 previously looked up.
4569 ***************************************************************************/
4571 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4572 uint32 version, BOOL delete_files )
4574 pstring key;
4575 const char *arch;
4576 TDB_DATA kbuf, dbuf;
4577 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4579 /* delete the tdb data first */
4581 arch = get_short_archi(info_3->environment);
4582 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4583 arch, version, info_3->name);
4585 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4586 key, delete_files ? "TRUE" : "FALSE" ));
4588 ctr.info_3 = info_3;
4589 dump_a_printer_driver( ctr, 3 );
4591 kbuf.dptr=key;
4592 kbuf.dsize=strlen(key)+1;
4594 /* check if the driver actually exists for this environment */
4596 dbuf = tdb_fetch( tdb_drivers, kbuf );
4597 if ( !dbuf.dptr ) {
4598 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4599 return WERR_UNKNOWN_PRINTER_DRIVER;
4602 SAFE_FREE( dbuf.dptr );
4604 /* ok... the driver exists so the delete should return success */
4606 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4607 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4608 return WERR_ACCESS_DENIED;
4612 * now delete any associated files if delete_files == True
4613 * even if this part failes, we return succes because the
4614 * driver doesn not exist any more
4617 if ( delete_files )
4618 delete_driver_files( info_3, user );
4621 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4623 return WERR_OK;
4626 /****************************************************************************
4627 Store a security desc for a printer.
4628 ****************************************************************************/
4630 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4632 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4633 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4634 prs_struct ps;
4635 TALLOC_CTX *mem_ctx = NULL;
4636 fstring key;
4637 WERROR status;
4639 mem_ctx = talloc_init("nt_printing_setsec");
4640 if (mem_ctx == NULL)
4641 return WERR_NOMEM;
4643 /* The old owner and group sids of the security descriptor are not
4644 present when new ACEs are added or removed by changing printer
4645 permissions through NT. If they are NULL in the new security
4646 descriptor then copy them over from the old one. */
4648 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4649 DOM_SID *owner_sid, *group_sid;
4650 SEC_ACL *dacl, *sacl;
4651 SEC_DESC *psd = NULL;
4652 size_t size;
4654 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4656 /* Pick out correct owner and group sids */
4658 owner_sid = secdesc_ctr->sec->owner_sid ?
4659 secdesc_ctr->sec->owner_sid :
4660 old_secdesc_ctr->sec->owner_sid;
4662 group_sid = secdesc_ctr->sec->grp_sid ?
4663 secdesc_ctr->sec->grp_sid :
4664 old_secdesc_ctr->sec->grp_sid;
4666 dacl = secdesc_ctr->sec->dacl ?
4667 secdesc_ctr->sec->dacl :
4668 old_secdesc_ctr->sec->dacl;
4670 sacl = secdesc_ctr->sec->sacl ?
4671 secdesc_ctr->sec->sacl :
4672 old_secdesc_ctr->sec->sacl;
4674 /* Make a deep copy of the security descriptor */
4676 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4677 owner_sid, group_sid,
4678 sacl,
4679 dacl,
4680 &size);
4682 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4685 if (!new_secdesc_ctr) {
4686 new_secdesc_ctr = secdesc_ctr;
4689 /* Store the security descriptor in a tdb */
4691 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4692 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4694 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4695 &ps, 1)) {
4696 status = WERR_BADFUNC;
4697 goto out;
4700 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4702 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4703 status = WERR_OK;
4704 } else {
4705 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4706 status = WERR_BADFUNC;
4709 /* Free malloc'ed memory */
4711 out:
4713 prs_mem_free(&ps);
4714 if (mem_ctx)
4715 talloc_destroy(mem_ctx);
4716 return status;
4719 /****************************************************************************
4720 Construct a default security descriptor buffer for a printer.
4721 ****************************************************************************/
4723 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4725 SEC_ACE ace[3];
4726 SEC_ACCESS sa;
4727 SEC_ACL *psa = NULL;
4728 SEC_DESC_BUF *sdb = NULL;
4729 SEC_DESC *psd = NULL;
4730 DOM_SID owner_sid;
4731 size_t sd_size;
4733 /* Create an ACE where Everyone is allowed to print */
4735 init_sec_access(&sa, PRINTER_ACE_PRINT);
4736 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4737 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4739 /* Make the security descriptor owned by the Administrators group
4740 on the PDC of the domain. */
4742 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4743 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4744 } else {
4746 /* Backup plan - make printer owned by admins.
4747 This should emulate a lanman printer as security
4748 settings can't be changed. */
4750 sid_copy(&owner_sid, get_global_sam_sid());
4751 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4754 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4755 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4756 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4757 SEC_ACE_FLAG_INHERIT_ONLY);
4759 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4760 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4761 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4763 /* The ACL revision number in rpc_secdesc.h differs from the one
4764 created by NT when setting ACE entries in printer
4765 descriptors. NT4 complains about the property being edited by a
4766 NT5 machine. */
4768 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4769 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4770 &owner_sid, NULL,
4771 NULL, psa, &sd_size);
4774 if (!psd) {
4775 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4776 return NULL;
4779 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4781 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4782 (unsigned int)sd_size));
4784 return sdb;
4787 /****************************************************************************
4788 Get a security desc for a printer.
4789 ****************************************************************************/
4791 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4793 prs_struct ps;
4794 fstring key;
4795 char *temp;
4797 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4798 printername = temp + 1;
4801 /* Fetch security descriptor from tdb */
4803 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4805 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4806 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4808 DEBUG(4,("using default secdesc for %s\n", printername));
4810 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4811 return False;
4814 /* Save default security descriptor for later */
4816 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4817 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4819 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4820 tdb_prs_store(tdb_printers, key, &ps);
4822 prs_mem_free(&ps);
4824 return True;
4827 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4828 this security descriptor has been created when winbindd was
4829 down. Take ownership of security descriptor. */
4831 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4832 DOM_SID owner_sid;
4834 /* Change sd owner to workgroup administrator */
4836 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4837 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4838 SEC_DESC *psd = NULL;
4839 size_t size;
4841 /* Create new sd */
4843 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4845 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4846 &owner_sid,
4847 (*secdesc_ctr)->sec->grp_sid,
4848 (*secdesc_ctr)->sec->sacl,
4849 (*secdesc_ctr)->sec->dacl,
4850 &size);
4852 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4854 /* Swap with other one */
4856 *secdesc_ctr = new_secdesc_ctr;
4858 /* Set it */
4860 nt_printing_setsec(printername, *secdesc_ctr);
4864 if (DEBUGLEVEL >= 10) {
4865 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4866 int i;
4868 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4869 printername, the_acl->num_aces));
4871 for (i = 0; i < the_acl->num_aces; i++) {
4872 fstring sid_str;
4874 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4876 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4877 the_acl->ace[i].type, the_acl->ace[i].flags,
4878 the_acl->ace[i].info.mask));
4882 prs_mem_free(&ps);
4883 return True;
4886 /* error code:
4887 0: everything OK
4888 1: level not implemented
4889 2: file doesn't exist
4890 3: can't allocate memory
4891 4: can't free memory
4892 5: non existant struct
4896 A printer and a printer driver are 2 different things.
4897 NT manages them separatelly, Samba does the same.
4898 Why ? Simply because it's easier and it makes sense !
4900 Now explanation: You have 3 printers behind your samba server,
4901 2 of them are the same make and model (laser A and B). But laser B
4902 has an 3000 sheet feeder and laser A doesn't such an option.
4903 Your third printer is an old dot-matrix model for the accounting :-).
4905 If the /usr/local/samba/lib directory (default dir), you will have
4906 5 files to describe all of this.
4908 3 files for the printers (1 by printer):
4909 NTprinter_laser A
4910 NTprinter_laser B
4911 NTprinter_accounting
4912 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4913 NTdriver_printer model X
4914 NTdriver_printer model Y
4916 jfm: I should use this comment for the text file to explain
4917 same thing for the forms BTW.
4918 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4922 /* Convert generic access rights to printer object specific access rights.
4923 It turns out that NT4 security descriptors use generic access rights and
4924 NT5 the object specific ones. */
4926 void map_printer_permissions(SEC_DESC *sd)
4928 int i;
4930 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4931 se_map_generic(&sd->dacl->ace[i].info.mask,
4932 &printer_generic_mapping);
4936 /****************************************************************************
4937 Check a user has permissions to perform the given operation. We use the
4938 permission constants defined in include/rpc_spoolss.h to check the various
4939 actions we perform when checking printer access.
4941 PRINTER_ACCESS_ADMINISTER:
4942 print_queue_pause, print_queue_resume, update_printer_sec,
4943 update_printer, spoolss_addprinterex_level_2,
4944 _spoolss_setprinterdata
4946 PRINTER_ACCESS_USE:
4947 print_job_start
4949 JOB_ACCESS_ADMINISTER:
4950 print_job_delete, print_job_pause, print_job_resume,
4951 print_queue_purge
4953 ****************************************************************************/
4954 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4956 SEC_DESC_BUF *secdesc = NULL;
4957 uint32 access_granted;
4958 NTSTATUS status;
4959 BOOL result;
4960 const char *pname;
4961 TALLOC_CTX *mem_ctx = NULL;
4962 extern struct current_user current_user;
4964 /* If user is NULL then use the current_user structure */
4966 if (!user)
4967 user = &current_user;
4969 /* Always allow root or printer admins to do anything */
4971 if (user->uid == 0 ||
4972 user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4973 return True;
4976 /* Get printer name */
4978 pname = PRINTERNAME(snum);
4980 if (!pname || !*pname) {
4981 errno = EACCES;
4982 return False;
4985 /* Get printer security descriptor */
4987 if(!(mem_ctx = talloc_init("print_access_check"))) {
4988 errno = ENOMEM;
4989 return False;
4992 nt_printing_getsec(mem_ctx, pname, &secdesc);
4994 if (access_type == JOB_ACCESS_ADMINISTER) {
4995 SEC_DESC_BUF *parent_secdesc = secdesc;
4997 /* Create a child security descriptor to check permissions
4998 against. This is because print jobs are child objects
4999 objects of a printer. */
5001 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5003 /* Now this is the bit that really confuses me. The access
5004 type needs to be changed from JOB_ACCESS_ADMINISTER to
5005 PRINTER_ACCESS_ADMINISTER for this to work. Something
5006 to do with the child (job) object becoming like a
5007 printer?? -tpot */
5009 access_type = PRINTER_ACCESS_ADMINISTER;
5012 /* Check access */
5014 map_printer_permissions(secdesc->sec);
5016 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5017 &access_granted, &status);
5019 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5021 talloc_destroy(mem_ctx);
5023 if (!result)
5024 errno = EACCES;
5026 return result;
5029 /****************************************************************************
5030 Check the time parameters allow a print operation.
5031 *****************************************************************************/
5033 BOOL print_time_access_check(int snum)
5035 NT_PRINTER_INFO_LEVEL *printer = NULL;
5036 BOOL ok = False;
5037 time_t now = time(NULL);
5038 struct tm *t;
5039 uint32 mins;
5041 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5042 return False;
5044 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5045 ok = True;
5047 t = gmtime(&now);
5048 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5050 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5051 ok = True;
5053 free_a_printer(&printer, 2);
5055 if (!ok)
5056 errno = EACCES;
5058 return ok;