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-2005.
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 3 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, see <http://www.gnu.org/licenses/>.
24
static TDB_CONTEXT *tdb_forms; /* used for forms files */
25
static TDB_CONTEXT *tdb_drivers; /* used for driver files */
26
static TDB_CONTEXT *tdb_printers; /* used for printers files */
28
#define FORMS_PREFIX "FORMS/"
29
#define DRIVERS_PREFIX "DRIVERS/"
30
#define DRIVER_INIT_PREFIX "DRIVER_INIT/"
31
#define PRINTERS_PREFIX "PRINTERS/"
32
#define SECDESC_PREFIX "SECDESC/"
33
#define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
35
#define NTDRIVERS_DATABASE_VERSION_1 1
36
#define NTDRIVERS_DATABASE_VERSION_2 2
37
#define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
38
#define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
39
#define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
41
/* Map generic permissions to printer object specific permissions */
43
const struct generic_mapping printer_generic_mapping = {
50
const struct standard_mapping printer_std_mapping = {
57
/* Map generic permissions to print server object specific permissions */
59
const struct generic_mapping printserver_generic_mapping = {
66
const struct generic_mapping printserver_std_mapping = {
73
/* Map generic permissions to job object specific permissions */
75
const struct generic_mapping job_generic_mapping = {
82
/* We need one default form to support our default printer. Msoft adds the
83
forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
84
array index). Letter is always first, so (for the current code) additions
85
always put things in the correct order. */
86
static const nt_forms_struct default_forms[] = {
87
{"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
88
{"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
89
{"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
90
{"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
91
{"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
92
{"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
93
{"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
94
{"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
95
{"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
96
{"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
97
{"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
98
{"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
99
{"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
100
{"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
101
{"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
102
{"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
103
{"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
104
{"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
105
{"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
106
{"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
107
{"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
108
{"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
109
{"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
110
{"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
111
{"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
112
{"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
113
{"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
114
{"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
115
{"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
116
{"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
117
{"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
118
{"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
119
{"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
120
{"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
121
{"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
122
{"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
123
{"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
124
{"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
125
{"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
126
{"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
127
{"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
128
{"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
129
{"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
130
{"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
131
{"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
132
{"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
133
{"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
134
{"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
135
{"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
136
{"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137
{"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
138
{"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
139
{"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
140
{"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
141
{"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
142
{"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
143
{"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
144
{"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
145
{"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
146
{"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
147
{"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
148
{"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
149
{"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
150
{"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
151
{"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
152
{"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
153
{"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
154
{"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
155
{"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
156
{"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
157
{"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
158
{"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
159
{"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
160
{"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
161
{"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
162
{"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
163
{"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
164
{"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
165
{"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
166
{"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
167
{"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
168
{"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
169
{"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
170
{"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
171
{"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
172
{"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
173
{"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
174
{"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
175
{"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
176
{"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
177
{"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
178
{"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
179
{"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
180
{"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
181
{"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
182
{"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
183
{"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
184
{"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
185
{"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
186
{"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
187
{"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
188
{"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
189
{"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
190
{"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
191
{"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
192
{"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
193
{"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
194
{"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
195
{"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
196
{"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
197
{"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
198
{"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
199
{"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
200
{"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
201
{"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
202
{"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
203
{"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
204
{"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
207
static const struct print_architecture_table_node archi_table[]= {
209
{"Windows 4.0", SPL_ARCH_WIN40, 0 },
210
{"Windows NT x86", SPL_ARCH_W32X86, 2 },
211
{"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
212
{"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
213
{"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
214
{"Windows IA64", SPL_ARCH_IA64, 3 },
215
{"Windows x64", SPL_ARCH_X64, 3 },
220
/****************************************************************************
221
generate a new TDB_DATA key for storing a printer
222
****************************************************************************/
224
static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
230
fstrcpy(share, sharename);
233
keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
234
key = string_term_tdb_data(keystr ? keystr : "");
239
/****************************************************************************
240
generate a new TDB_DATA key for storing a printer security descriptor
241
****************************************************************************/
243
static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
244
const char* sharename )
250
fstrcpy(share, sharename );
253
keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
254
key = string_term_tdb_data(keystr ? keystr : "");
259
/****************************************************************************
260
****************************************************************************/
262
static bool upgrade_to_version_3(void)
264
TDB_DATA kbuf, newkey, dbuf;
266
DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
268
for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
269
newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
271
dbuf = tdb_fetch(tdb_drivers, kbuf);
273
if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
274
DEBUG(0,("upgrade_to_version_3:moving form\n"));
275
if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
276
SAFE_FREE(dbuf.dptr);
277
DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
280
if (tdb_delete(tdb_drivers, kbuf) != 0) {
281
SAFE_FREE(dbuf.dptr);
282
DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
287
if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
288
DEBUG(0,("upgrade_to_version_3:moving printer\n"));
289
if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
290
SAFE_FREE(dbuf.dptr);
291
DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
294
if (tdb_delete(tdb_drivers, kbuf) != 0) {
295
SAFE_FREE(dbuf.dptr);
296
DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
301
if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
302
DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
303
if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
304
SAFE_FREE(dbuf.dptr);
305
DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
308
if (tdb_delete(tdb_drivers, kbuf) != 0) {
309
SAFE_FREE(dbuf.dptr);
310
DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
315
SAFE_FREE(dbuf.dptr);
321
/*******************************************************************
322
Fix an issue with security descriptors. Printer sec_desc must
323
use more than the generic bits that were previously used
324
in <= 3.0.14a. They must also have a owner and group SID assigned.
325
Otherwise, any printers than have been migrated to a Windows
326
host using printmig.exe will not be accessible.
327
*******************************************************************/
329
static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
330
TDB_DATA data, void *state )
333
SEC_DESC_BUF *sd_orig = NULL;
334
SEC_DESC_BUF *sd_new, *sd_store;
335
SEC_DESC *sec, *new_sec;
336
TALLOC_CTX *ctx = state;
341
if (!data.dptr || data.dsize == 0) {
345
if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
349
/* upgrade the security descriptor */
351
status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
352
if (!NT_STATUS_IS_OK(status)) {
353
/* delete bad entries */
354
DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
355
(const char *)key.dptr ));
356
tdb_delete( tdb_printers, key );
365
/* is this even valid? */
371
/* update access masks */
373
for ( i=0; i<sec->dacl->num_aces; i++ ) {
374
switch ( sec->dacl->aces[i].access_mask ) {
375
case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
376
sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
379
case GENERIC_ALL_ACCESS:
380
sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
383
case READ_CONTROL_ACCESS:
384
sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
386
default: /* no change */
391
/* create a new SEC_DESC with the appropriate owner and group SIDs */
393
new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
394
&global_sid_Builtin_Administrators,
395
&global_sid_Builtin_Administrators,
396
NULL, NULL, &size_new_sec );
400
sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
405
if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
406
DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
412
sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0)
413
+ sizeof(SEC_DESC_BUF);
415
status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
416
if (!NT_STATUS_IS_OK(status)) {
417
DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
421
result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
423
/* 0 to continue and non-zero to stop traversal */
425
return (result == -1);
428
/*******************************************************************
429
*******************************************************************/
431
static bool upgrade_to_version_4(void)
436
DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
438
if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
441
result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
443
talloc_destroy( ctx );
445
return ( result != -1 );
448
/*******************************************************************
449
Fix an issue with security descriptors. Printer sec_desc must
450
use more than the generic bits that were previously used
451
in <= 3.0.14a. They must also have a owner and group SID assigned.
452
Otherwise, any printers than have been migrated to a Windows
453
host using printmig.exe will not be accessible.
454
*******************************************************************/
456
static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
457
TDB_DATA data, void *state )
459
TALLOC_CTX *ctx = talloc_tos();
462
if (!data.dptr || data.dsize == 0)
465
/* upgrade printer records and security descriptors */
467
if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
468
new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
470
else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
471
new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
474
/* ignore this record */
478
/* delete the original record and store under the normalized key */
480
if ( tdb_delete( the_tdb, key ) != 0 ) {
481
DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
486
if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
487
DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
495
/*******************************************************************
496
*******************************************************************/
498
static bool upgrade_to_version_5(void)
503
DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
505
if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
508
result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
510
talloc_destroy( ctx );
512
return ( result != -1 );
515
/****************************************************************************
516
Open the NT printing tdbs. Done once before fork().
517
****************************************************************************/
519
bool nt_printing_init(struct messaging_context *msg_ctx)
521
const char *vstring = "INFO/version";
525
if ( tdb_drivers && tdb_printers && tdb_forms )
529
tdb_close(tdb_drivers);
530
tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
532
DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
533
state_path("ntdrivers.tdb"), strerror(errno) ));
538
tdb_close(tdb_printers);
539
tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
541
DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
542
state_path("ntprinters.tdb"), strerror(errno) ));
547
tdb_close(tdb_forms);
548
tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
550
DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
551
state_path("ntforms.tdb"), strerror(errno) ));
555
/* handle a Samba upgrade */
557
vers_id = tdb_fetch_int32(tdb_drivers, vstring);
559
DEBUG(10, ("Fresh database\n"));
560
tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
561
vers_id = NTDRIVERS_DATABASE_VERSION_5;
564
if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
566
if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
567
if (!upgrade_to_version_3())
569
tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
570
vers_id = NTDRIVERS_DATABASE_VERSION_3;
573
if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
574
/* Written on a bigendian machine with old fetch_int code. Save as le. */
575
/* The only upgrade between V2 and V3 is to save the version in little-endian. */
576
tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
577
vers_id = NTDRIVERS_DATABASE_VERSION_3;
580
if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
581
if ( !upgrade_to_version_4() )
583
tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
584
vers_id = NTDRIVERS_DATABASE_VERSION_4;
587
if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
588
if ( !upgrade_to_version_5() )
590
tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
591
vers_id = NTDRIVERS_DATABASE_VERSION_5;
595
if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
596
DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
601
update_c_setprinter(True);
604
* register callback to handle updating printers as new
605
* drivers are installed
608
messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
609
do_drv_upgrade_printer);
612
* register callback to handle updating printer data
613
* when a driver is initialized
616
messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
617
reset_all_printerdata);
619
/* of course, none of the message callbacks matter if you don't
620
tell messages.c that you interested in receiving PRINT_GENERAL
621
msgs. This is done in claim_connection() */
624
if ( lp_security() == SEC_ADS ) {
625
win_rc = check_published_printers();
626
if (!W_ERROR_IS_OK(win_rc))
627
DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
633
/*******************************************************************
634
Function to allow filename parsing "the old way".
635
********************************************************************/
637
static char *driver_unix_convert(connection_struct *conn,
638
const char *old_name,
639
SMB_STRUCT_STAT *pst)
641
TALLOC_CTX *ctx = talloc_tos();
642
char *name = talloc_strdup(ctx, old_name);
643
char *new_name = NULL;
649
name = unix_clean_name(ctx, name);
653
trim_string(name,"/","/");
654
unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
658
/*******************************************************************
659
tdb traversal function for counting printers.
660
********************************************************************/
662
static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
663
TDB_DATA data, void *context)
665
int *printer_count = (int*)context;
667
if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
669
DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
675
/*******************************************************************
676
Update the spooler global c_setprinter. This variable is initialized
677
when the parent smbd starts with the number of existing printers. It
678
is monotonically increased by the current number of printers *after*
679
each add or delete printer RPC. Only Microsoft knows why... JRR020119
680
********************************************************************/
682
uint32 update_c_setprinter(bool initialize)
685
int32 printer_count = 0;
687
tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
689
/* Traverse the tdb, counting the printers */
690
tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
692
/* If initializing, set c_setprinter to current printers count
693
* otherwise, bump it by the current printer count
696
c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
698
c_setprinter = printer_count;
700
DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
701
tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
703
tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
705
return (uint32)c_setprinter;
708
/*******************************************************************
709
Get the spooler global c_setprinter, accounting for initialization.
710
********************************************************************/
712
uint32 get_c_setprinter(void)
714
int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
716
if (c_setprinter == (int32)-1)
717
c_setprinter = update_c_setprinter(True);
719
DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
721
return (uint32)c_setprinter;
724
/****************************************************************************
725
Get builtin form struct list.
726
****************************************************************************/
728
int get_builtin_ntforms(nt_forms_struct **list)
730
*list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
734
return ARRAY_SIZE(default_forms);
737
/****************************************************************************
738
get a builtin form struct
739
****************************************************************************/
741
bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
744
DEBUGADD(6,("Looking for builtin form %s \n", form_name));
745
for (i=0; i<ARRAY_SIZE(default_forms); i++) {
746
if (strequal(form_name,default_forms[i].name)) {
747
DEBUGADD(6,("Found builtin form %s \n", form_name));
748
memcpy(form,&default_forms[i],sizeof(*form));
756
/****************************************************************************
757
get a form struct list.
758
****************************************************************************/
760
int get_ntforms(nt_forms_struct **list)
762
TDB_DATA kbuf, newkey, dbuf;
763
nt_forms_struct form;
770
for (kbuf = tdb_firstkey(tdb_forms);
772
newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
774
if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
777
dbuf = tdb_fetch(tdb_forms, kbuf);
781
fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
782
ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
783
&i, &form.flag, &form.width, &form.length, &form.left,
784
&form.top, &form.right, &form.bottom);
785
SAFE_FREE(dbuf.dptr);
786
if (ret != dbuf.dsize)
789
*list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
791
DEBUG(0,("get_ntforms: Realloc fail.\n"));
802
/****************************************************************************
803
write a form struct list
804
****************************************************************************/
806
int write_ntforms(nt_forms_struct **list, int number)
808
TALLOC_CTX *ctx = talloc_tos();
815
for (i=0;i<number;i++) {
816
/* save index, so list is rebuilt in correct order */
817
len = tdb_pack(NULL, 0, "dddddddd",
818
i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
819
(*list)[i].left, (*list)[i].top, (*list)[i].right,
824
buf = TALLOC_ARRAY(ctx, char, len);
828
len = tdb_pack((uint8 *)buf, len, "dddddddd",
829
i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
830
(*list)[i].left, (*list)[i].top, (*list)[i].right,
832
key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
837
dbuf.dptr = (uint8 *)buf;
838
if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
850
/****************************************************************************
851
add a form struct at the end of the list
852
****************************************************************************/
853
bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
859
* NT tries to add forms even when
860
* they are already in the base
861
* only update the values if already present
866
for (n=0; n<*count; n++) {
867
if ( strequal((*list)[n].name, form->form_name) ) {
874
if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
875
DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
878
fstrcpy((*list)[n].name, form->form_name);
882
(*list)[n].flag = form->flags;
883
(*list)[n].width = form->size.width;
884
(*list)[n].length = form->size.height;
885
(*list)[n].left = form->area.left;
886
(*list)[n].top = form->area.top;
887
(*list)[n].right = form->area.right;
888
(*list)[n].bottom = form->area.bottom;
890
DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
891
update ? "updated" : "added", form->form_name));
896
/****************************************************************************
897
Delete a named form struct.
898
****************************************************************************/
900
bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
907
for (n=0; n<*count; n++) {
908
if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
909
DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
915
DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
916
*ret = WERR_INVALID_PARAM;
920
if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
924
if (tdb_delete_bystring(tdb_forms, key) != 0) {
933
/****************************************************************************
934
Update a form struct.
935
****************************************************************************/
937
void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
941
DEBUG(106, ("[%s]\n", form->form_name));
942
for (n=0; n<count; n++) {
943
DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
944
if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
948
if (n==count) return;
950
(*list)[n].flag = form->flags;
951
(*list)[n].width = form->size.width;
952
(*list)[n].length = form->size.height;
953
(*list)[n].left = form->area.left;
954
(*list)[n].top = form->area.top;
955
(*list)[n].right = form->area.right;
956
(*list)[n].bottom = form->area.bottom;
959
/****************************************************************************
960
Get the nt drivers list.
961
Traverse the database and look-up the matching names.
962
****************************************************************************/
963
int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
966
const char *short_archi;
968
TDB_DATA kbuf, newkey;
970
short_archi = get_short_archi(architecture);
975
if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
976
short_archi, version) < 0) {
980
for (kbuf = tdb_firstkey(tdb_drivers);
982
newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
984
if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
987
if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
988
DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
993
fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1001
/****************************************************************************
1002
Function to do the mapping between the long architecture name and
1004
****************************************************************************/
1006
const char *get_short_archi(const char *long_archi)
1010
DEBUG(107,("Getting architecture dependant directory\n"));
1013
} while ( (archi_table[i].long_archi!=NULL ) &&
1014
StrCaseCmp(long_archi, archi_table[i].long_archi) );
1016
if (archi_table[i].long_archi==NULL) {
1017
DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1021
/* this might be client code - but shouldn't this be an fstrcpy etc? */
1023
DEBUGADD(108,("index: [%d]\n", i));
1024
DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1025
DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1027
return archi_table[i].short_archi;
1030
/****************************************************************************
1031
Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1032
There are two case to be covered here: PE (Portable Executable) and NE (New
1033
Executable) files. Both files support the same INFO structure, but PE files
1034
store the signature in unicode, and NE files store it as !unicode.
1035
returns -1 on error, 1 on version info found, and 0 on no version info found.
1036
****************************************************************************/
1038
static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1044
if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1045
DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1046
fname, DOS_HEADER_SIZE));
1050
if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1051
DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1052
fname, (unsigned long)byte_count));
1053
goto no_version_info;
1056
/* Is this really a DOS header? */
1057
if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1058
DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1059
fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1060
goto no_version_info;
1063
/* Skip OEM header (if any) and the DOS stub to start of Windows header */
1064
if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1065
DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1067
/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1068
goto no_version_info;
1071
/* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1072
if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1073
DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1074
fname, (unsigned long)byte_count));
1075
/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1076
goto no_version_info;
1079
/* The header may be a PE (Portable Executable) or an NE (New Executable) */
1080
if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1081
unsigned int num_sections;
1082
unsigned int section_table_bytes;
1084
/* Just skip over optional header to get to section table */
1085
if (SMB_VFS_LSEEK(fsp,
1086
SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1087
SEEK_CUR) == (SMB_OFF_T)-1) {
1088
DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1093
/* get the section table */
1094
num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1095
section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1096
if (section_table_bytes == 0)
1100
if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1101
DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1102
fname, section_table_bytes));
1106
if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1107
DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1108
fname, (unsigned long)byte_count));
1112
/* Iterate the section table looking for the resource section ".rsrc" */
1113
for (i = 0; i < num_sections; i++) {
1114
int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1116
if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1117
unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1118
unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1120
if (section_bytes == 0)
1124
if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1125
DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1126
fname, section_bytes));
1130
/* Seek to the start of the .rsrc section info */
1131
if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1132
DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1137
if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1138
DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1139
fname, (unsigned long)byte_count));
1143
if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1146
for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1147
/* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1148
if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1149
/* Align to next long address */
1150
int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1152
if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1153
*major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1154
*minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1156
DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1157
fname, *major, *minor,
1158
(*major>>16)&0xffff, *major&0xffff,
1159
(*minor>>16)&0xffff, *minor&0xffff));
1168
/* Version info not found, fall back to origin date/time */
1169
DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1173
} else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1174
if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1175
DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1176
fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1177
/* At this point, we assume the file is in error. It still could be somthing
1178
* else besides a NE file, but it unlikely at this point. */
1182
/* Allocate a bit more space to speed up things */
1184
if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1185
DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1186
fname, PE_HEADER_SIZE));
1190
/* This is a HACK! I got tired of trying to sort through the messy
1191
* 'NE' file format. If anyone wants to clean this up please have at
1192
* it, but this works. 'NE' files will eventually fade away. JRR */
1193
while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1194
/* Cover case that should not occur in a well formed 'NE' .dll file */
1195
if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1197
for(i=0; i<byte_count; i++) {
1198
/* Fast skip past data that can't possibly match */
1199
if (buf[i] != 'V') continue;
1201
/* Potential match data crosses buf boundry, move it to beginning
1202
* of buf, and fill the buf with as much as it will hold. */
1203
if (i>byte_count-VS_VERSION_INFO_SIZE) {
1206
memcpy(buf, &buf[i], byte_count-i);
1207
if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1208
(byte_count-i))) < 0) {
1210
DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1215
byte_count = bc + (byte_count - i);
1216
if (byte_count<VS_VERSION_INFO_SIZE) break;
1221
/* Check that the full signature string and the magic number that
1222
* follows exist (not a perfect solution, but the chances that this
1223
* occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1224
* twice, as it is simpler to read the code. */
1225
if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1226
/* Compute skip alignment to next long address */
1227
int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1228
sizeof(VS_SIGNATURE)) & 3;
1229
if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1231
*major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1232
*minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1233
DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1234
fname, *major, *minor,
1235
(*major>>16)&0xffff, *major&0xffff,
1236
(*minor>>16)&0xffff, *minor&0xffff));
1243
/* Version info not found, fall back to origin date/time */
1244
DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1249
/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1250
DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1251
fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1262
/****************************************************************************
1263
Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1264
share one or more files. During the MS installation process files are checked
1265
to insure that only a newer version of a shared file is installed over an
1266
older version. There are several possibilities for this comparison. If there
1267
is no previous version, the new one is newer (obviously). If either file is
1268
missing the version info structure, compare the creation date (on Unix use
1269
the modification date). Otherwise chose the numerically larger version number.
1270
****************************************************************************/
1272
static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1274
bool use_version = true;
1275
char *filepath = NULL;
1279
time_t new_create_time;
1283
time_t old_create_time;
1285
files_struct *fsp = NULL;
1287
SMB_STRUCT_STAT stat_buf;
1291
SET_STAT_INVALID(st);
1292
SET_STAT_INVALID(stat_buf);
1293
new_create_time = (time_t)0;
1294
old_create_time = (time_t)0;
1296
/* Get file version info (if available) for previous file (if it exists) */
1297
filepath = driver_unix_convert(conn,old_file,&stat_buf);
1302
status = SMB_VFS_CREATE_FILE(
1305
0, /* root_dir_fid */
1306
filepath, /* fname */
1307
0, /* create_file_flags */
1308
FILE_GENERIC_READ, /* access_mask */
1309
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1310
FILE_OPEN, /* create_disposition*/
1311
0, /* create_options */
1312
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1313
INTERNAL_OPEN_ONLY, /* oplock_request */
1314
0, /* allocation_size */
1319
&stat_buf); /* psbuf */
1321
if (!NT_STATUS_IS_OK(status)) {
1322
/* Old file not found, so by definition new file is in fact newer */
1323
DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1328
int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1334
DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1336
use_version = false;
1337
if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1340
old_create_time = st.st_mtime;
1341
DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1342
(long)old_create_time));
1345
close_file(NULL, fsp, NORMAL_CLOSE);
1348
/* Get file version info (if available) for new file */
1349
filepath = driver_unix_convert(conn,new_file,&stat_buf);
1354
status = SMB_VFS_CREATE_FILE(
1357
0, /* root_dir_fid */
1358
filepath, /* fname */
1359
0, /* create_file_flags */
1360
FILE_GENERIC_READ, /* access_mask */
1361
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1362
FILE_OPEN, /* create_disposition*/
1363
0, /* create_options */
1364
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1365
INTERNAL_OPEN_ONLY, /* oplock_request */
1366
0, /* allocation_size */
1371
&stat_buf); /* psbuf */
1373
if (!NT_STATUS_IS_OK(status)) {
1374
/* New file not found, this shouldn't occur if the caller did its job */
1375
DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1380
int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1386
DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1388
use_version = false;
1389
if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1392
new_create_time = st.st_mtime;
1393
DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1394
(long)new_create_time));
1397
close_file(NULL, fsp, NORMAL_CLOSE);
1400
if (use_version && (new_major != old_major || new_minor != old_minor)) {
1401
/* Compare versions and choose the larger version number */
1402
if (new_major > old_major ||
1403
(new_major == old_major && new_minor > old_minor)) {
1405
DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1409
DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1414
/* Compare modification time/dates and choose the newest time/date */
1415
if (new_create_time > old_create_time) {
1416
DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1420
DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1427
close_file(NULL, fsp, NORMAL_CLOSE);
1431
/****************************************************************************
1432
Determine the correct cVersion associated with an architecture and driver
1433
****************************************************************************/
1434
static uint32 get_correct_cversion(struct pipes_struct *p,
1435
const char *architecture,
1436
fstring driverpath_in,
1441
char *driverpath = NULL;
1442
files_struct *fsp = NULL;
1444
connection_struct *conn = NULL;
1447
fstring printdollar;
1448
int printdollar_snum;
1450
SET_STAT_INVALID(st);
1452
*perr = WERR_INVALID_PARAM;
1454
/* If architecture is Windows 95/98/ME, the version is always 0. */
1455
if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1456
DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1461
/* If architecture is Windows x64, the version is always 3. */
1462
if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1463
DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1468
fstrcpy(printdollar, "print$");
1470
printdollar_snum = find_service(printdollar);
1471
if (printdollar_snum == -1) {
1472
*perr = WERR_NO_SUCH_SHARE;
1476
nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1477
lp_pathname(printdollar_snum),
1478
p->server_info, &oldcwd);
1479
if (!NT_STATUS_IS_OK(nt_status)) {
1480
DEBUG(0,("get_correct_cversion: create_conn_struct "
1481
"returned %s\n", nt_errstr(nt_status)));
1482
*perr = ntstatus_to_werror(nt_status);
1486
/* Open the driver file (Portable Executable format) and determine the
1487
* deriver the cversion. */
1488
driverpath = talloc_asprintf(talloc_tos(),
1497
driverpath = driver_unix_convert(conn,driverpath,&st);
1503
if (!vfs_file_exist(conn, driverpath, &st)) {
1504
*perr = WERR_BADFILE;
1508
status = SMB_VFS_CREATE_FILE(
1511
0, /* root_dir_fid */
1512
driverpath, /* fname */
1513
0, /* create_file_flags */
1514
FILE_GENERIC_READ, /* access_mask */
1515
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1516
FILE_OPEN, /* create_disposition*/
1517
0, /* create_options */
1518
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1519
INTERNAL_OPEN_ONLY, /* oplock_request */
1520
0, /* allocation_size */
1527
if (!NT_STATUS_IS_OK(status)) {
1528
DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1529
driverpath, errno));
1530
*perr = WERR_ACCESS_DENIED;
1535
int ret = get_file_version(fsp, driverpath, &major, &minor);
1536
if (ret == -1) goto error_exit;
1539
DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1544
* This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1545
* for more details. Version in this case is not just the version of the
1546
* file, but the version in the sense of kernal mode (2) vs. user mode
1547
* (3) drivers. Other bits of the version fields are the version info.
1550
cversion = major & 0x0000ffff;
1552
case 2: /* WinNT drivers */
1553
case 3: /* Win2K drivers */
1557
DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1558
driverpath, cversion));
1562
DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1563
driverpath, major, minor));
1566
DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1567
driverpath, cversion));
1575
close_file(NULL, fsp, NORMAL_CLOSE);
1578
vfs_ChDir(conn, oldcwd);
1579
conn_free_internal(conn);
1581
if (cversion != -1) {
1587
/****************************************************************************
1588
****************************************************************************/
1589
static WERROR clean_up_driver_struct_level_3(struct pipes_struct *rpc_pipe,
1590
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1592
const char *architecture;
1598
/* clean up the driver name.
1599
* we can get .\driver.dll
1600
* or worse c:\windows\system\driver.dll !
1602
/* using an intermediate string to not have overlaping memcpy()'s */
1603
if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1604
fstrcpy(new_name, p+1);
1605
fstrcpy(driver->driverpath, new_name);
1608
if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1609
fstrcpy(new_name, p+1);
1610
fstrcpy(driver->datafile, new_name);
1613
if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1614
fstrcpy(new_name, p+1);
1615
fstrcpy(driver->configfile, new_name);
1618
if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1619
fstrcpy(new_name, p+1);
1620
fstrcpy(driver->helpfile, new_name);
1623
if (driver->dependentfiles) {
1624
for (i=0; *driver->dependentfiles[i]; i++) {
1625
if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1626
fstrcpy(new_name, p+1);
1627
fstrcpy(driver->dependentfiles[i], new_name);
1632
architecture = get_short_archi(driver->environment);
1633
if (!architecture) {
1634
return WERR_UNKNOWN_PRINTER_DRIVER;
1637
/* jfm:7/16/2000 the client always sends the cversion=0.
1638
* The server should check which version the driver is by reading
1639
* the PE header of driver->driverpath.
1641
* For Windows 95/98 the version is 0 (so the value sent is correct)
1642
* For Windows NT (the architecture doesn't matter)
1643
* NT 3.1: cversion=0
1644
* NT 3.5/3.51: cversion=1
1648
if ((driver->cversion = get_correct_cversion(rpc_pipe, architecture,
1656
/****************************************************************************
1657
****************************************************************************/
1658
static WERROR clean_up_driver_struct_level_6(struct pipes_struct *rpc_pipe,
1659
NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1661
const char *architecture;
1667
/* clean up the driver name.
1668
* we can get .\driver.dll
1669
* or worse c:\windows\system\driver.dll !
1671
/* using an intermediate string to not have overlaping memcpy()'s */
1672
if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1673
fstrcpy(new_name, p+1);
1674
fstrcpy(driver->driverpath, new_name);
1677
if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1678
fstrcpy(new_name, p+1);
1679
fstrcpy(driver->datafile, new_name);
1682
if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1683
fstrcpy(new_name, p+1);
1684
fstrcpy(driver->configfile, new_name);
1687
if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1688
fstrcpy(new_name, p+1);
1689
fstrcpy(driver->helpfile, new_name);
1692
if (driver->dependentfiles) {
1693
for (i=0; *driver->dependentfiles[i]; i++) {
1694
if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1695
fstrcpy(new_name, p+1);
1696
fstrcpy(driver->dependentfiles[i], new_name);
1701
architecture = get_short_archi(driver->environment);
1702
if (!architecture) {
1703
return WERR_UNKNOWN_PRINTER_DRIVER;
1706
/* jfm:7/16/2000 the client always sends the cversion=0.
1707
* The server should check which version the driver is by reading
1708
* the PE header of driver->driverpath.
1710
* For Windows 95/98 the version is 0 (so the value sent is correct)
1711
* For Windows NT (the architecture doesn't matter)
1712
* NT 3.1: cversion=0
1713
* NT 3.5/3.51: cversion=1
1718
if ((driver->version = get_correct_cversion(rpc_pipe, architecture,
1726
/****************************************************************************
1727
****************************************************************************/
1728
WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
1729
NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1735
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1736
driver=driver_abstract.info_3;
1737
return clean_up_driver_struct_level_3(rpc_pipe,
1742
NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1743
driver=driver_abstract.info_6;
1744
return clean_up_driver_struct_level_6(rpc_pipe,
1748
return WERR_INVALID_PARAM;
1752
/****************************************************************************
1753
This function sucks and should be replaced. JRA.
1754
****************************************************************************/
1756
static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1758
dst->cversion = src->version;
1760
fstrcpy( dst->name, src->name);
1761
fstrcpy( dst->environment, src->environment);
1762
fstrcpy( dst->driverpath, src->driverpath);
1763
fstrcpy( dst->datafile, src->datafile);
1764
fstrcpy( dst->configfile, src->configfile);
1765
fstrcpy( dst->helpfile, src->helpfile);
1766
fstrcpy( dst->monitorname, src->monitorname);
1767
fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1768
dst->dependentfiles = src->dependentfiles;
1771
#if 0 /* Debugging function */
1773
static char* ffmt(unsigned char *c){
1775
static char ffmt_str[17];
1777
for (i=0; i<16; i++) {
1778
if ((c[i] < ' ') || (c[i] > '~'))
1789
/****************************************************************************
1790
****************************************************************************/
1792
static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1793
connection_struct *conn,
1794
const char *driver_file,
1795
const char *short_architecture,
1796
uint32_t driver_version,
1799
char *old_name = NULL;
1800
char *new_name = NULL;
1804
old_name = talloc_asprintf(mem_ctx, "%s/%s",
1805
short_architecture, driver_file);
1806
W_ERROR_HAVE_NO_MEMORY(old_name);
1808
new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1809
short_architecture, driver_version, driver_file);
1810
W_ERROR_HAVE_NO_MEMORY(new_name);
1812
if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1814
old_name = driver_unix_convert(conn, old_name, &st);
1815
W_ERROR_HAVE_NO_MEMORY(old_name);
1817
DEBUG(10,("move_driver_file_to_download_area: copying '%s' to '%s'\n",
1818
old_name, new_name));
1820
status = copy_file(mem_ctx, conn, old_name, new_name,
1821
OPENX_FILE_EXISTS_TRUNCATE |
1822
OPENX_FILE_CREATE_IF_NOT_EXIST,
1825
if (!NT_STATUS_IS_OK(status)) {
1826
DEBUG(0,("move_driver_file_to_download_area: Unable to rename [%s] to [%s]: %s\n",
1827
old_name, new_name, nt_errstr(status)));
1828
return WERR_ACCESS_DENIED;
1835
WERROR move_driver_to_download_area(struct pipes_struct *p,
1836
NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1837
uint32 level, WERROR *perr)
1839
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1840
NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1841
const char *short_architecture;
1842
char *new_dir = NULL;
1843
connection_struct *conn = NULL;
1847
TALLOC_CTX *ctx = talloc_tos();
1850
fstring printdollar;
1851
int printdollar_snum;
1857
driver = driver_abstract.info_3;
1860
convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1861
driver = &converted_driver;
1864
DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1865
return WERR_UNKNOWN_LEVEL;
1868
short_architecture = get_short_archi(driver->environment);
1869
if (!short_architecture) {
1870
return WERR_UNKNOWN_PRINTER_DRIVER;
1873
fstrcpy(printdollar, "print$");
1875
printdollar_snum = find_service(printdollar);
1876
if (printdollar_snum == -1) {
1877
*perr = WERR_NO_SUCH_SHARE;
1878
return WERR_NO_SUCH_SHARE;
1881
nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1882
lp_pathname(printdollar_snum),
1883
p->server_info, &oldcwd);
1884
if (!NT_STATUS_IS_OK(nt_status)) {
1885
DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1886
"returned %s\n", nt_errstr(nt_status)));
1887
*perr = ntstatus_to_werror(nt_status);
1891
new_dir = talloc_asprintf(ctx,
1899
new_dir = driver_unix_convert(conn,new_dir,&st);
1905
DEBUG(5,("Creating first directory: %s\n", new_dir));
1907
create_directory(conn, NULL, new_dir);
1909
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1910
* listed for this driver which has already been moved, skip it (note:
1911
* drivers may list the same file name several times. Then check if the
1912
* file already exists in archi\cversion\, if so, check that the version
1913
* info (or time stamps if version info is unavailable) is newer (or the
1914
* date is later). If it is, move it to archi\cversion\filexxx.yyy.
1915
* Otherwise, delete the file.
1917
* If a file is not moved to archi\cversion\ because of an error, all the
1918
* rest of the 'unmoved' driver files are removed from archi\. If one or
1919
* more of the driver's files was already moved to archi\cversion\, it
1920
* potentially leaves the driver in a partially updated state. Version
1921
* trauma will most likely occur if an client attempts to use any printer
1922
* bound to the driver. Perhaps a rewrite to make sure the moves can be
1923
* done is appropriate... later JRR
1926
DEBUG(5,("Moving files now !\n"));
1928
if (driver->driverpath && strlen(driver->driverpath)) {
1930
*perr = move_driver_file_to_download_area(ctx,
1936
if (!W_ERROR_IS_OK(*perr)) {
1937
if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1944
if (driver->datafile && strlen(driver->datafile)) {
1945
if (!strequal(driver->datafile, driver->driverpath)) {
1947
*perr = move_driver_file_to_download_area(ctx,
1953
if (!W_ERROR_IS_OK(*perr)) {
1954
if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1962
if (driver->configfile && strlen(driver->configfile)) {
1963
if (!strequal(driver->configfile, driver->driverpath) &&
1964
!strequal(driver->configfile, driver->datafile)) {
1966
*perr = move_driver_file_to_download_area(ctx,
1972
if (!W_ERROR_IS_OK(*perr)) {
1973
if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1981
if (driver->helpfile && strlen(driver->helpfile)) {
1982
if (!strequal(driver->helpfile, driver->driverpath) &&
1983
!strequal(driver->helpfile, driver->datafile) &&
1984
!strequal(driver->helpfile, driver->configfile)) {
1986
*perr = move_driver_file_to_download_area(ctx,
1992
if (!W_ERROR_IS_OK(*perr)) {
1993
if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2001
if (driver->dependentfiles) {
2002
for (i=0; *driver->dependentfiles[i]; i++) {
2003
if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
2004
!strequal(driver->dependentfiles[i], driver->datafile) &&
2005
!strequal(driver->dependentfiles[i], driver->configfile) &&
2006
!strequal(driver->dependentfiles[i], driver->helpfile)) {
2008
for (j=0; j < i; j++) {
2009
if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
2014
*perr = move_driver_file_to_download_area(ctx,
2016
driver->dependentfiles[i],
2020
if (!W_ERROR_IS_OK(*perr)) {
2021
if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2034
vfs_ChDir(conn, oldcwd);
2035
conn_free_internal(conn);
2038
if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2042
return WERR_UNKNOWN_PRINTER_DRIVER;
2047
/****************************************************************************
2048
****************************************************************************/
2050
static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
2052
TALLOC_CTX *ctx = talloc_tos();
2054
const char *architecture;
2055
char *directory = NULL;
2062
architecture = get_short_archi(driver->environment);
2063
if (!architecture) {
2067
/* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2068
* \\server is added in the rpc server layer.
2069
* It does make sense to NOT store the server's name in the printer TDB.
2072
directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2073
architecture, driver->cversion);
2078
/* .inf files do not always list a file for each of the four standard files.
2079
* Don't prepend a path to a null filename, or client claims:
2080
* "The server on which the printer resides does not have a suitable
2081
* <printer driver name> printer driver installed. Click OK if you
2082
* wish to install the driver on your local machine."
2084
if (strlen(driver->driverpath)) {
2085
fstrcpy(temp_name, driver->driverpath);
2086
slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
2089
if (strlen(driver->datafile)) {
2090
fstrcpy(temp_name, driver->datafile);
2091
slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
2094
if (strlen(driver->configfile)) {
2095
fstrcpy(temp_name, driver->configfile);
2096
slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
2099
if (strlen(driver->helpfile)) {
2100
fstrcpy(temp_name, driver->helpfile);
2101
slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
2104
if (driver->dependentfiles) {
2105
for (i=0; *driver->dependentfiles[i]; i++) {
2106
fstrcpy(temp_name, driver->dependentfiles[i]);
2107
slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
2111
key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2112
architecture, driver->cversion, driver->name);
2117
DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2124
len += tdb_pack(buf+len, buflen-len, "dffffffff",
2127
driver->environment,
2132
driver->monitorname,
2133
driver->defaultdatatype);
2135
if (driver->dependentfiles) {
2136
for (i=0; *driver->dependentfiles[i]; i++) {
2137
len += tdb_pack(buf+len, buflen-len, "f",
2138
driver->dependentfiles[i]);
2142
if (len != buflen) {
2143
buf = (uint8 *)SMB_REALLOC(buf, len);
2145
DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2156
ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2160
DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2166
/****************************************************************************
2167
****************************************************************************/
2168
static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2170
NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2173
info3.cversion = driver->version;
2174
fstrcpy(info3.name,driver->name);
2175
fstrcpy(info3.environment,driver->environment);
2176
fstrcpy(info3.driverpath,driver->driverpath);
2177
fstrcpy(info3.datafile,driver->datafile);
2178
fstrcpy(info3.configfile,driver->configfile);
2179
fstrcpy(info3.helpfile,driver->helpfile);
2180
fstrcpy(info3.monitorname,driver->monitorname);
2181
fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2182
info3.dependentfiles = driver->dependentfiles;
2184
return add_a_printer_driver_3(&info3);
2188
/****************************************************************************
2189
****************************************************************************/
2190
static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2192
NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2196
fstrcpy(info.name, driver);
2197
fstrcpy(info.defaultdatatype, "RAW");
2199
fstrcpy(info.driverpath, "");
2200
fstrcpy(info.datafile, "");
2201
fstrcpy(info.configfile, "");
2202
fstrcpy(info.helpfile, "");
2204
if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2207
memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2208
fstrcpy(info.dependentfiles[0], "");
2210
*info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2212
SAFE_FREE(info.dependentfiles);
2219
/****************************************************************************
2220
****************************************************************************/
2221
static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
2222
const char *drivername, const char *arch,
2225
NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2227
const char *architecture;
2232
ZERO_STRUCT(driver);
2234
architecture = get_short_archi(arch);
2235
if ( !architecture ) {
2236
return WERR_UNKNOWN_PRINTER_DRIVER;
2239
/* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2241
if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2244
DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2246
if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2247
architecture, version, drivername) < 0) {
2251
dbuf = tdb_fetch_bystring(tdb_drivers, key);
2254
return WERR_UNKNOWN_PRINTER_DRIVER;
2257
len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2266
driver.defaultdatatype);
2269
while (len < dbuf.dsize) {
2270
driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2271
if ( !driver.dependentfiles ) {
2272
DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2276
len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2277
&driver.dependentfiles[i]);
2281
if ( driver.dependentfiles )
2282
fstrcpy( driver.dependentfiles[i], "" );
2284
SAFE_FREE(dbuf.dptr);
2287
if (len != dbuf.dsize) {
2288
SAFE_FREE(driver.dependentfiles);
2290
return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2293
*info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2295
SAFE_FREE(driver.dependentfiles);
2302
/****************************************************************************
2303
Debugging function, dump at level 6 the struct in the logs.
2304
****************************************************************************/
2306
static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2309
NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2312
DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2318
if (driver.info_3 == NULL)
2321
info3=driver.info_3;
2323
DEBUGADD(20,("version:[%d]\n", info3->cversion));
2324
DEBUGADD(20,("name:[%s]\n", info3->name));
2325
DEBUGADD(20,("environment:[%s]\n", info3->environment));
2326
DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2327
DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2328
DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2329
DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2330
DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2331
DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2333
for (i=0; info3->dependentfiles &&
2334
*info3->dependentfiles[i]; i++) {
2335
DEBUGADD(20,("dependentfile:[%s]\n",
2336
info3->dependentfiles[i]));
2343
DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2351
/****************************************************************************
2352
****************************************************************************/
2353
int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2357
len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2362
len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2363
nt_devmode->devicename,
2364
nt_devmode->formname,
2366
nt_devmode->specversion,
2367
nt_devmode->driverversion,
2369
nt_devmode->driverextra,
2370
nt_devmode->orientation,
2371
nt_devmode->papersize,
2372
nt_devmode->paperlength,
2373
nt_devmode->paperwidth,
2376
nt_devmode->defaultsource,
2377
nt_devmode->printquality,
2380
nt_devmode->yresolution,
2381
nt_devmode->ttoption,
2382
nt_devmode->collate,
2383
nt_devmode->logpixels,
2386
nt_devmode->bitsperpel,
2387
nt_devmode->pelswidth,
2388
nt_devmode->pelsheight,
2389
nt_devmode->displayflags,
2390
nt_devmode->displayfrequency,
2391
nt_devmode->icmmethod,
2392
nt_devmode->icmintent,
2393
nt_devmode->mediatype,
2394
nt_devmode->dithertype,
2395
nt_devmode->reserved1,
2396
nt_devmode->reserved2,
2397
nt_devmode->panningwidth,
2398
nt_devmode->panningheight,
2399
nt_devmode->nt_dev_private);
2401
if (nt_devmode->nt_dev_private) {
2402
len += tdb_pack(buf+len, buflen-len, "B",
2403
nt_devmode->driverextra,
2404
nt_devmode->nt_dev_private);
2407
DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2412
/****************************************************************************
2413
Pack all values in all printer keys
2414
***************************************************************************/
2416
static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2420
REGISTRY_VALUE *val;
2421
REGVAL_CTR *val_ctr;
2428
/* loop over all keys */
2430
for ( i=0; i<data->num_keys; i++ ) {
2431
val_ctr = data->keys[i].values;
2432
num_values = regval_ctr_numvals( val_ctr );
2434
/* pack the keyname followed by a empty value */
2436
len += tdb_pack(buf+len, buflen-len, "pPdB",
2437
&data->keys[i].name,
2443
/* now loop over all values */
2445
for ( j=0; j<num_values; j++ ) {
2446
/* pathname should be stored as <key>\<value> */
2448
val = regval_ctr_specific_value( val_ctr, j );
2449
if (asprintf(&path, "%s\\%s",
2451
regval_name(val)) < 0) {
2455
len += tdb_pack(buf+len, buflen-len, "pPdB",
2460
regval_data_p(val) );
2462
DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2470
len += tdb_pack(buf+len, buflen-len, "p", NULL);
2476
/****************************************************************************
2477
Delete a printer - this just deletes the printer info file, any open
2478
handles are not affected.
2479
****************************************************************************/
2481
uint32 del_a_printer(const char *sharename)
2484
char *printdb_path = NULL;
2485
TALLOC_CTX *ctx = talloc_tos();
2487
kbuf = make_printer_tdbkey(ctx, sharename);
2488
tdb_delete(tdb_printers, kbuf);
2490
kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2491
tdb_delete(tdb_printers, kbuf);
2493
close_all_print_db();
2495
if (geteuid() == 0) {
2496
if (asprintf(&printdb_path, "%s%s.tdb",
2497
cache_path("printing/"),
2501
unlink(printdb_path);
2502
SAFE_FREE(printdb_path);
2508
/****************************************************************************
2509
****************************************************************************/
2510
static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2516
TDB_DATA kbuf, dbuf;
2519
* in addprinter: no servername and the printer is the name
2520
* in setprinter: servername is \\server
2521
* and printer is \\server\\printer
2523
* Samba manages only local printers.
2524
* we currently don't support things like i
2525
* path=\\other_server\printer
2527
* We only store the printername, not \\server\printername
2530
if ( info->servername[0] != '\0' ) {
2531
trim_string(info->printername, info->servername, NULL);
2532
trim_char(info->printername, '\\', '\0');
2533
info->servername[0]='\0';
2537
* JFM: one day I'll forget.
2538
* below that's info->portname because that's the SAMBA sharename
2539
* and I made NT 'thinks' it's the portname
2540
* the info->sharename is the thing you can name when you add a printer
2541
* that's the short-name when you create shared printer for 95/98
2542
* So I've made a limitation in SAMBA: you can only have 1 printer model
2543
* behind a SAMBA share.
2551
len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2554
info->default_priority,
2571
info->printprocessor,
2575
len += pack_devicemode(info->devmode, buf+len, buflen-len);
2576
retlen = pack_values( info->data, buf+len, buflen-len );
2583
if (buflen != len) {
2584
buf = (uint8 *)SMB_REALLOC(buf, len);
2586
DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2594
kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2599
ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2602
if (!W_ERROR_IS_OK(ret))
2603
DEBUG(8, ("error updating printer to tdb on disk\n"));
2607
DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2608
info->sharename, info->drivername, info->portname, len));
2614
/****************************************************************************
2615
Malloc and return an NT devicemode.
2616
****************************************************************************/
2618
NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2621
char adevice[MAXDEVICENAME];
2622
NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2624
if (nt_devmode == NULL) {
2625
DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2629
ZERO_STRUCTP(nt_devmode);
2631
slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2632
fstrcpy(nt_devmode->devicename, adevice);
2634
fstrcpy(nt_devmode->formname, "Letter");
2636
nt_devmode->specversion = 0x0401;
2637
nt_devmode->driverversion = 0x0400;
2638
nt_devmode->size = 0x00DC;
2639
nt_devmode->driverextra = 0x0000;
2640
nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2641
DEFAULTSOURCE | COPIES | SCALE |
2642
PAPERSIZE | ORIENTATION;
2643
nt_devmode->orientation = 1;
2644
nt_devmode->papersize = PAPER_LETTER;
2645
nt_devmode->paperlength = 0;
2646
nt_devmode->paperwidth = 0;
2647
nt_devmode->scale = 0x64;
2648
nt_devmode->copies = 1;
2649
nt_devmode->defaultsource = BIN_FORMSOURCE;
2650
nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2651
nt_devmode->color = COLOR_MONOCHROME;
2652
nt_devmode->duplex = DUP_SIMPLEX;
2653
nt_devmode->yresolution = 0;
2654
nt_devmode->ttoption = TT_SUBDEV;
2655
nt_devmode->collate = COLLATE_FALSE;
2656
nt_devmode->icmmethod = 0;
2657
nt_devmode->icmintent = 0;
2658
nt_devmode->mediatype = 0;
2659
nt_devmode->dithertype = 0;
2661
/* non utilisés par un driver d'imprimante */
2662
nt_devmode->logpixels = 0;
2663
nt_devmode->bitsperpel = 0;
2664
nt_devmode->pelswidth = 0;
2665
nt_devmode->pelsheight = 0;
2666
nt_devmode->displayflags = 0;
2667
nt_devmode->displayfrequency = 0;
2668
nt_devmode->reserved1 = 0;
2669
nt_devmode->reserved2 = 0;
2670
nt_devmode->panningwidth = 0;
2671
nt_devmode->panningheight = 0;
2673
nt_devmode->nt_dev_private = NULL;
2677
/****************************************************************************
2678
Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2679
****************************************************************************/
2681
void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2683
NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2685
if(nt_devmode == NULL)
2688
DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2690
SAFE_FREE(nt_devmode->nt_dev_private);
2691
SAFE_FREE(*devmode_ptr);
2694
/****************************************************************************
2695
Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2696
****************************************************************************/
2698
static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2700
NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2705
free_nt_devicemode(&info->devmode);
2707
TALLOC_FREE( *info_ptr );
2711
/****************************************************************************
2712
****************************************************************************/
2713
int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2717
NT_DEVICEMODE devmode;
2719
ZERO_STRUCT(devmode);
2721
len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2723
if (!*nt_devmode) return len;
2725
len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2729
&devmode.specversion,
2730
&devmode.driverversion,
2732
&devmode.driverextra,
2733
&devmode.orientation,
2735
&devmode.paperlength,
2736
&devmode.paperwidth,
2739
&devmode.defaultsource,
2740
&devmode.printquality,
2743
&devmode.yresolution,
2749
&devmode.bitsperpel,
2751
&devmode.pelsheight,
2752
&devmode.displayflags,
2753
&devmode.displayfrequency,
2757
&devmode.dithertype,
2760
&devmode.panningwidth,
2761
&devmode.panningheight,
2762
&devmode.nt_dev_private);
2764
if (devmode.nt_dev_private) {
2765
/* the len in tdb_unpack is an int value and
2766
* devmode.driverextra is only a short
2768
len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2769
devmode.driverextra=(uint16)extra_len;
2771
/* check to catch an invalid TDB entry so we don't segfault */
2772
if (devmode.driverextra == 0) {
2773
devmode.nt_dev_private = NULL;
2777
*nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2779
SAFE_FREE(devmode.nt_dev_private);
2783
DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2784
if (devmode.nt_dev_private)
2785
DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2790
/****************************************************************************
2791
Allocate and initialize a new slot.
2792
***************************************************************************/
2794
int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2799
if ( !name || !data )
2802
/* allocate another slot in the NT_PRINTER_KEY array */
2804
if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2805
DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2811
key_index = data->num_keys;
2813
/* initialze new key */
2815
data->keys[key_index].name = talloc_strdup( data, name );
2817
if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2822
DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2827
/****************************************************************************
2828
search for a registry key name in the existing printer data
2829
***************************************************************************/
2831
int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2835
for ( i=0; i<data->num_keys; i++ ) {
2836
if ( strequal( data->keys[i].name, name ) ) {
2838
/* cleanup memory */
2840
TALLOC_FREE( data->keys[i].name );
2841
TALLOC_FREE( data->keys[i].values );
2843
/* if not the end of the array, move remaining elements down one slot */
2846
if ( data->num_keys && (i < data->num_keys) )
2847
memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2854
return data->num_keys;
2857
/****************************************************************************
2858
search for a registry key name in the existing printer data
2859
***************************************************************************/
2861
int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2866
if ( !data || !name )
2869
DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2871
/* loop over all existing keys */
2873
for ( i=0; i<data->num_keys; i++ ) {
2874
if ( strequal(data->keys[i].name, name) ) {
2875
DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2885
/****************************************************************************
2886
***************************************************************************/
2888
int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2892
int num_subkeys = 0;
2894
fstring *subkeys_ptr = NULL;
2905
/* special case of asking for the top level printer data registry key names */
2907
if ( strlen(key) == 0 ) {
2908
for ( i=0; i<data->num_keys; i++ ) {
2910
/* found a match, so allocate space and copy the name */
2912
if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2913
DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2918
fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2925
/* asking for the subkeys of some key */
2926
/* subkey paths are stored in the key name using '\' as the delimiter */
2928
for ( i=0; i<data->num_keys; i++ ) {
2929
if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2931
/* if we found the exact key, then break */
2932
key_len = strlen( key );
2933
if ( strlen(data->keys[i].name) == key_len )
2936
/* get subkey path */
2938
p = data->keys[i].name + key_len;
2941
fstrcpy( subkeyname, p );
2942
if ( (p = strchr( subkeyname, '\\' )) )
2945
/* don't add a key more than once */
2947
for ( j=0; j<num_subkeys; j++ ) {
2948
if ( strequal( subkeys_ptr[j], subkeyname ) )
2952
if ( j != num_subkeys )
2955
/* found a match, so allocate space and copy the name */
2957
if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2958
DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2963
fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2969
/* return error if the key was not found */
2971
if ( i == data->num_keys ) {
2972
SAFE_FREE(subkeys_ptr);
2977
/* tag off the end */
2980
fstrcpy(subkeys_ptr[num_subkeys], "" );
2982
*subkeys = subkeys_ptr;
2988
static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2991
smb_ucs2_t conv_str[1024];
2994
regval_ctr_delvalue(ctr, val_name);
2995
str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2996
STR_TERMINATE | STR_NOALIGN);
2997
regval_ctr_addvalue(ctr, val_name, REG_SZ,
2998
(char *) conv_str, str_size);
3001
static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3004
regval_ctr_delvalue(ctr, val_name);
3005
regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3006
(char *) &dword, sizeof(dword));
3009
static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3012
uint8 bin_bool = (b ? 1 : 0);
3013
regval_ctr_delvalue(ctr, val_name);
3014
regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3015
(char *) &bin_bool, sizeof(bin_bool));
3018
static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3019
const char *multi_sz)
3021
smb_ucs2_t *conv_strs = NULL;
3024
/* a multi-sz has to have a null string terminator, i.e., the last
3025
string must be followed by two nulls */
3026
str_size = strlen(multi_sz) + 2;
3027
conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
3032
/* Change to byte units. */
3033
str_size *= sizeof(smb_ucs2_t);
3034
push_ucs2(NULL, conv_strs, multi_sz, str_size,
3035
STR_TERMINATE | STR_NOALIGN);
3037
regval_ctr_delvalue(ctr, val_name);
3038
regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
3039
(char *) conv_strs, str_size);
3040
SAFE_FREE(conv_strs);
3043
/****************************************************************************
3044
* Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3046
* @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3047
* @return bool indicating success or failure
3048
***************************************************************************/
3050
static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3052
REGVAL_CTR *ctr = NULL;
3054
const char *dnssuffix;
3055
char *allocated_string = NULL;
3056
const char *ascii_str;
3059
if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3060
i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3061
ctr = info2->data->keys[i].values;
3063
map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3064
map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3066
/* we make the assumption that the netbios name is the same
3067
as the DNS name sinc ethe former will be what we used to
3070
dnssuffix = get_mydnsdomname(talloc_tos());
3071
if (dnssuffix && *dnssuffix) {
3072
fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3074
fstrcpy( longname, global_myname() );
3077
map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3079
if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3082
map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3083
SAFE_FREE(allocated_string);
3085
map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3086
map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3087
map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3088
map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3089
map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3090
map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3091
map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3092
map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3093
map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3095
map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3096
(info2->attributes &
3097
PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3099
switch (info2->attributes & 0x3) {
3101
ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3104
ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3107
ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3110
ascii_str = "unknown";
3112
map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3117
/*****************************************************************
3118
****************************************************************/
3120
static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3124
REGVAL_CTR *ctr=NULL;
3125
UNISTR2 unistr_guid;
3127
/* find the DsSpooler key */
3128
if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3129
i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3130
ctr = info2->data->keys[i].values;
3132
regval_ctr_delvalue(ctr, "objectGUID");
3134
/* We used to store this as a REG_BINARY but that causes
3137
ZERO_STRUCT( unistr_guid );
3139
init_unistr2( &unistr_guid, GUID_string(talloc_tos(), &guid),
3140
UNI_STR_TERMINATE );
3142
regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3143
(char *)unistr_guid.buffer,
3144
unistr_guid.uni_max_len*2);
3148
static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3149
NT_PRINTER_INFO_LEVEL *printer)
3153
char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3154
char *srv_dn_utf8, **srv_cn_utf8;
3157
const char *attrs[] = {"objectGUID", NULL};
3159
WERROR win_rc = WERR_OK;
3160
size_t converted_size;
3162
/* build the ads mods */
3163
ctx = talloc_init("nt_printer_publish_ads");
3168
DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3170
/* figure out where to publish */
3171
ads_find_machine_acct(ads, &res, global_myname());
3173
/* We use ldap_get_dn here as we need the answer
3174
* in utf8 to call ldap_explode_dn(). JRA. */
3176
srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3179
return WERR_SERVER_UNAVAILABLE;
3181
ads_msgfree(ads, res);
3182
srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3185
ldap_memfree(srv_dn_utf8);
3186
return WERR_SERVER_UNAVAILABLE;
3188
/* Now convert to CH_UNIX. */
3189
if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3191
ldap_memfree(srv_dn_utf8);
3192
ldap_memfree(srv_cn_utf8);
3193
return WERR_SERVER_UNAVAILABLE;
3195
if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3197
ldap_memfree(srv_dn_utf8);
3198
ldap_memfree(srv_cn_utf8);
3199
TALLOC_FREE(srv_dn);
3200
return WERR_SERVER_UNAVAILABLE;
3203
ldap_memfree(srv_dn_utf8);
3204
ldap_memfree(srv_cn_utf8);
3206
srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3207
if (!srv_cn_escaped) {
3209
return WERR_SERVER_UNAVAILABLE;
3211
sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3212
if (!sharename_escaped) {
3213
SAFE_FREE(srv_cn_escaped);
3215
return WERR_SERVER_UNAVAILABLE;
3218
prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3220
SAFE_FREE(srv_cn_escaped);
3221
SAFE_FREE(sharename_escaped);
3223
mods = ads_init_mods(ctx);
3231
get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3232
ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3233
printer->info_2->sharename);
3236
ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3237
if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3239
for (i=0; mods[i] != 0; i++)
3241
mods[i] = (LDAPMod *)-1;
3242
ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3245
if (!ADS_ERR_OK(ads_rc))
3246
DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3248
/* retreive the guid and store it locally */
3249
if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3251
ads_pull_guid(ads, res, &guid);
3252
ads_msgfree(ads, res);
3253
store_printer_guid(printer->info_2, guid);
3254
win_rc = mod_a_printer(printer, 2);
3261
static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3262
NT_PRINTER_INFO_LEVEL *printer)
3265
LDAPMessage *res = NULL;
3266
char *prt_dn = NULL;
3268
DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3270
/* remove the printer from the directory */
3271
ads_rc = ads_find_printer_on_server(ads, &res,
3272
printer->info_2->sharename, global_myname());
3274
if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3275
prt_dn = ads_get_dn(ads, talloc_tos(), res);
3277
ads_msgfree(ads, res);
3280
ads_rc = ads_del_dn(ads, prt_dn);
3281
TALLOC_FREE(prt_dn);
3285
ads_msgfree(ads, res);
3290
/****************************************************************************
3291
* Publish a printer in the directory
3293
* @param snum describing printer service
3294
* @return WERROR indicating status of publishing
3295
***************************************************************************/
3297
WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3300
ADS_STRUCT *ads = NULL;
3301
NT_PRINTER_INFO_LEVEL *printer = NULL;
3304
win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3305
if (!W_ERROR_IS_OK(win_rc))
3309
case DSPRINT_PUBLISH:
3310
case DSPRINT_UPDATE:
3311
/* set the DsSpooler info and attributes */
3312
if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3313
win_rc = WERR_NOMEM;
3317
printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3319
case DSPRINT_UNPUBLISH:
3320
printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3323
win_rc = WERR_NOT_SUPPORTED;
3327
win_rc = mod_a_printer(printer, 2);
3328
if (!W_ERROR_IS_OK(win_rc)) {
3329
DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3333
ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3335
DEBUG(3, ("ads_init() failed\n"));
3336
win_rc = WERR_SERVER_UNAVAILABLE;
3339
setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3340
SAFE_FREE(ads->auth.password);
3341
ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3344
/* ads_connect() will find the DC for us */
3345
ads_rc = ads_connect(ads);
3346
if (!ADS_ERR_OK(ads_rc)) {
3347
DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3348
win_rc = WERR_ACCESS_DENIED;
3353
case DSPRINT_PUBLISH:
3354
case DSPRINT_UPDATE:
3355
win_rc = nt_printer_publish_ads(ads, printer);
3357
case DSPRINT_UNPUBLISH:
3358
win_rc = nt_printer_unpublish_ads(ads, printer);
3363
free_a_printer(&printer, 2);
3368
WERROR check_published_printers(void)
3371
ADS_STRUCT *ads = NULL;
3373
int n_services = lp_numservices();
3374
NT_PRINTER_INFO_LEVEL *printer = NULL;
3376
ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3378
DEBUG(3, ("ads_init() failed\n"));
3379
return WERR_SERVER_UNAVAILABLE;
3381
setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3382
SAFE_FREE(ads->auth.password);
3383
ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3386
/* ads_connect() will find the DC for us */
3387
ads_rc = ads_connect(ads);
3388
if (!ADS_ERR_OK(ads_rc)) {
3389
DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3391
ads_kdestroy("MEMORY:prtpub_cache");
3392
return WERR_ACCESS_DENIED;
3395
for (snum = 0; snum < n_services; snum++) {
3396
if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3399
if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3400
lp_servicename(snum))) &&
3401
(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3402
nt_printer_publish_ads(ads, printer);
3404
free_a_printer(&printer, 2);
3408
ads_kdestroy("MEMORY:prtpub_cache");
3412
bool is_printer_published(Printer_entry *print_hnd, int snum,
3415
NT_PRINTER_INFO_LEVEL *printer = NULL;
3417
REGISTRY_VALUE *guid_val;
3422
win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3424
if (!W_ERROR_IS_OK(win_rc) ||
3425
!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3426
((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3427
!(ctr = printer->info_2->data->keys[i].values) ||
3428
!(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3430
free_a_printer(&printer, 2);
3434
/* fetching printer guids really ought to be a separate function. */
3439
/* We used to store the guid as REG_BINARY, then swapped
3440
to REG_SZ for Vista compatibility so check for both */
3442
switch ( regval_type(guid_val) ){
3444
rpcstr_pull( guid_str, regval_data_p(guid_val),
3445
sizeof(guid_str)-1, -1, STR_TERMINATE );
3446
ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3449
if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3453
memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3456
DEBUG(0,("is_printer_published: GUID value stored as "
3457
"invaluid type (%d)\n", regval_type(guid_val) ));
3462
free_a_printer(&printer, 2);
3466
WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3471
WERROR check_published_printers(void)
3476
bool is_printer_published(Printer_entry *print_hnd, int snum,
3481
#endif /* HAVE_ADS */
3483
/****************************************************************************
3484
***************************************************************************/
3486
WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3488
NT_PRINTER_DATA *data;
3490
int removed_keys = 0;
3494
empty_slot = data->num_keys;
3497
return WERR_INVALID_PARAM;
3499
/* remove all keys */
3501
if ( !strlen(key) ) {
3503
TALLOC_FREE( data );
3507
DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3513
/* remove a specific key (and all subkeys) */
3515
for ( i=0; i<data->num_keys; i++ ) {
3516
if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3517
DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3518
data->keys[i].name));
3520
TALLOC_FREE( data->keys[i].name );
3521
TALLOC_FREE( data->keys[i].values );
3523
/* mark the slot as empty */
3525
ZERO_STRUCTP( &data->keys[i] );
3529
/* find the first empty slot */
3531
for ( i=0; i<data->num_keys; i++ ) {
3532
if ( !data->keys[i].name ) {
3539
if ( i == data->num_keys )
3540
/* nothing was removed */
3541
return WERR_INVALID_PARAM;
3543
/* move everything down */
3545
for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3546
if ( data->keys[i].name ) {
3547
memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3548
ZERO_STRUCTP( &data->keys[i] );
3556
data->num_keys -= removed_keys;
3558
/* sanity check to see if anything is left */
3560
if ( !data->num_keys ) {
3561
DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3563
SAFE_FREE( data->keys );
3564
ZERO_STRUCTP( data );
3570
/****************************************************************************
3571
***************************************************************************/
3573
WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3575
WERROR result = WERR_OK;
3578
/* we must have names on non-zero length */
3580
if ( !key || !*key|| !value || !*value )
3581
return WERR_INVALID_NAME;
3583
/* find the printer key first */
3585
key_index = lookup_printerkey( p2->data, key );
3586
if ( key_index == -1 )
3589
/* make sure the value exists so we can return the correct error code */
3591
if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3592
return WERR_BADFILE;
3594
regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3596
DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3602
/****************************************************************************
3603
***************************************************************************/
3605
WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3606
uint32 type, uint8 *data, int real_len )
3608
WERROR result = WERR_OK;
3611
/* we must have names on non-zero length */
3613
if ( !key || !*key|| !value || !*value )
3614
return WERR_INVALID_NAME;
3616
/* find the printer key first */
3618
key_index = lookup_printerkey( p2->data, key );
3619
if ( key_index == -1 )
3620
key_index = add_new_printer_key( p2->data, key );
3622
if ( key_index == -1 )
3625
regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3626
type, (const char *)data, real_len );
3628
DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3629
key, value, type, real_len ));
3634
/****************************************************************************
3635
***************************************************************************/
3637
REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3641
if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3644
DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3647
return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3650
/****************************************************************************
3651
Unpack a list of registry values frem the TDB
3652
***************************************************************************/
3654
static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3659
const char *valuename = NULL;
3660
const char *keyname = NULL;
3664
REGISTRY_VALUE *regval_p;
3667
/* add the "PrinterDriverData" key first for performance reasons */
3669
add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3671
/* loop and unpack the rest of the registry values */
3675
/* check to see if there are any more registry values */
3678
len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3682
/* unpack the next regval */
3684
len += tdb_unpack(buf+len, buflen-len, "fdB",
3690
/* lookup for subkey names which have a type of REG_NONE */
3691
/* there's no data with this entry */
3693
if ( type == REG_NONE ) {
3694
if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3695
add_new_printer_key( printer_data, string );
3700
* break of the keyname from the value name.
3701
* Valuenames can have embedded '\'s so be careful.
3702
* only support one level of keys. See the
3703
* "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3707
str = strchr_m( string, '\\');
3709
/* Put in "PrinterDriverData" is no key specified */
3712
keyname = SPOOL_PRINTERDATA_KEY;
3721
/* see if we need a new key */
3723
if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3724
key_index = add_new_printer_key( printer_data, keyname );
3726
if ( key_index == -1 ) {
3727
DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3732
DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3734
/* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3735
Thanks to Martin Zielinski for the hint. */
3737
if ( type == REG_BINARY &&
3738
strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3739
strequal( valuename, "objectGUID" ) )
3742
UNISTR2 unistr_guid;
3744
ZERO_STRUCT( unistr_guid );
3746
/* convert the GUID to a UNICODE string */
3748
memcpy( &guid, data_p, sizeof(struct GUID) );
3750
init_unistr2( &unistr_guid,
3751
GUID_string(talloc_tos(), &guid),
3752
UNI_STR_TERMINATE );
3754
regval_ctr_addvalue( printer_data->keys[key_index].values,
3756
(const char *)unistr_guid.buffer,
3757
unistr_guid.uni_str_len*2 );
3762
regval_ctr_addvalue( printer_data->keys[key_index].values,
3763
valuename, type, (const char *)data_p,
3767
SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3774
/****************************************************************************
3775
***************************************************************************/
3777
static char *last_from;
3778
static char *last_to;
3780
static const char *get_last_from(void)
3788
static const char *get_last_to(void)
3796
static bool set_last_from_to(const char *from, const char *to)
3798
char *orig_from = last_from;
3799
char *orig_to = last_to;
3801
last_from = SMB_STRDUP(from);
3802
last_to = SMB_STRDUP(to);
3804
SAFE_FREE(orig_from);
3807
if (!last_from || !last_to) {
3808
SAFE_FREE(last_from);
3815
static void map_to_os2_driver(fstring drivername)
3817
char *mapfile = lp_os2_driver_map();
3818
char **lines = NULL;
3822
if (!strlen(drivername))
3828
if (strequal(drivername,get_last_from())) {
3829
DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3830
drivername,get_last_to()));
3831
fstrcpy(drivername,get_last_to());
3835
lines = file_lines_load(mapfile, &numlines,0,NULL);
3836
if (numlines == 0 || lines == NULL) {
3837
DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3842
DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3844
for( i = 0; i < numlines; i++) {
3845
char *nt_name = lines[i];
3846
char *os2_name = strchr(nt_name,'=');
3853
while (isspace(*nt_name))
3856
if (!*nt_name || strchr("#;",*nt_name))
3860
int l = strlen(nt_name);
3861
while (l && isspace(nt_name[l-1])) {
3867
while (isspace(*os2_name))
3871
int l = strlen(os2_name);
3872
while (l && isspace(os2_name[l-1])) {
3878
if (strequal(nt_name,drivername)) {
3879
DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3880
set_last_from_to(drivername,os2_name);
3881
fstrcpy(drivername,os2_name);
3890
/****************************************************************************
3891
Get a default printer info 2 struct.
3892
****************************************************************************/
3894
static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3895
const char *servername,
3896
const char* sharename,
3899
int snum = lp_servicenumber(sharename);
3901
slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3902
slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3903
servername, sharename);
3904
fstrcpy(info->sharename, sharename);
3905
fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3907
/* by setting the driver name to an empty string, a local NT admin
3908
can now run the **local** APW to install a local printer driver
3909
for a Samba shared printer in 2.2. Without this, drivers **must** be
3910
installed on the Samba server for NT clients --jerry */
3911
#if 0 /* JERRY --do not uncomment-- */
3912
if (!*info->drivername)
3913
fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3917
DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3919
strlcpy(info->comment, "", sizeof(info->comment));
3920
fstrcpy(info->printprocessor, "winprint");
3921
fstrcpy(info->datatype, "RAW");
3924
if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3925
/* Pull the location and comment strings from cups if we don't
3927
if ( !strlen(info->location) || !strlen(info->comment) )
3928
cups_pull_comment_location( info );
3932
info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3934
info->starttime = 0; /* Minutes since 12:00am GMT */
3935
info->untiltime = 0; /* Minutes since 12:00am GMT */
3937
info->default_priority = 1;
3938
info->setuptime = (uint32)time(NULL);
3941
* I changed this as I think it is better to have a generic
3942
* DEVMODE than to crash Win2k explorer.exe --jerry
3943
* See the HP Deskjet 990c Win2k drivers for an example.
3945
* However the default devmode appears to cause problems
3946
* with the HP CLJ 8500 PCL driver. Hence the addition of
3947
* the "default devmode" parameter --jerry 22/01/2002
3950
if (lp_default_devmode(snum)) {
3951
if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3955
info->devmode = NULL;
3958
if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3966
free_nt_devicemode(&info->devmode);
3968
return WERR_ACCESS_DENIED;
3971
/****************************************************************************
3972
****************************************************************************/
3974
static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
3975
const char *servername,
3976
const char *sharename,
3980
int snum = lp_servicenumber(sharename);
3981
TDB_DATA kbuf, dbuf;
3982
fstring printername;
3983
char adevice[MAXDEVICENAME];
3984
char *comment = NULL;
3986
kbuf = make_printer_tdbkey(talloc_tos(), sharename);
3988
dbuf = tdb_fetch(tdb_printers, kbuf);
3990
return get_a_printer_2_default(info, servername,
3991
sharename, get_loc_com);
3994
len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3997
&info->default_priority,
4004
&info->c_setprinter,
4014
info->printprocessor,
4019
strlcpy(info->comment, comment, sizeof(info->comment));
4023
/* Samba has to have shared raw drivers. */
4024
info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4025
info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4027
/* Restore the stripped strings. */
4028
slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4030
if ( lp_force_printername(snum) ) {
4031
slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4033
slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4036
fstrcpy(info->printername, printername);
4039
if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4040
/* Pull the location and comment strings from cups if we don't
4042
if ( !strlen(info->location) || !strlen(info->comment) )
4043
cups_pull_comment_location( info );
4047
len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4050
* Some client drivers freak out if there is a NULL devmode
4051
* (probably the driver is not checking before accessing
4052
* the devmode pointer) --jerry
4054
* See comments in get_a_printer_2_default()
4057
if (lp_default_devmode(snum) && !info->devmode) {
4058
DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4060
info->devmode = construct_nt_devicemode(printername);
4063
slprintf( adevice, sizeof(adevice), "%s", info->printername );
4064
if (info->devmode) {
4065
fstrcpy(info->devmode->devicename, adevice);
4068
if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4069
DEBUG(0,("unpack_values: talloc() failed!\n"));
4070
SAFE_FREE(dbuf.dptr);
4073
len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4075
/* This will get the current RPC talloc context, but we should be
4076
passing this as a parameter... fixme... JRA ! */
4078
if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4079
SAFE_FREE(dbuf.dptr);
4083
/* Fix for OS/2 drivers. */
4085
if (get_remote_arch() == RA_OS2) {
4086
map_to_os2_driver(info->drivername);
4089
SAFE_FREE(dbuf.dptr);
4091
DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4092
sharename, info->printername, info->drivername));
4097
/****************************************************************************
4098
Debugging function, dump at level 6 the struct in the logs.
4099
****************************************************************************/
4100
static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4103
NT_PRINTER_INFO_LEVEL_2 *info2;
4105
DEBUG(106,("Dumping printer at level [%d]\n", level));
4110
if (printer->info_2 == NULL)
4114
info2=printer->info_2;
4116
DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4117
DEBUGADD(106,("priority:[%d]\n", info2->priority));
4118
DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4119
DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4120
DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4121
DEBUGADD(106,("status:[%d]\n", info2->status));
4122
DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4123
DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4124
DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4125
DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4126
DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4128
DEBUGADD(106,("servername:[%s]\n", info2->servername));
4129
DEBUGADD(106,("printername:[%s]\n", info2->printername));
4130
DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4131
DEBUGADD(106,("portname:[%s]\n", info2->portname));
4132
DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4133
DEBUGADD(106,("comment:[%s]\n", info2->comment));
4134
DEBUGADD(106,("location:[%s]\n", info2->location));
4135
DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4136
DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4137
DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4138
DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4144
DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4152
/****************************************************************************
4153
Update the changeid time.
4154
This is SO NASTY as some drivers need this to change, others need it
4155
static. This value will change every second, and I must hope that this
4156
is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4158
****************************************************************************/
4160
static uint32 rev_changeid(void)
4164
get_process_uptime(&tv);
4167
/* Return changeid as msec since spooler restart */
4168
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4171
* This setting seems to work well but is too untested
4172
* to replace the above calculation. Left in for experiementation
4173
* of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4175
return tv.tv_sec * 10 + tv.tv_usec / 100000;
4181
* The function below are the high level ones.
4182
* only those ones must be called from the spoolss code.
4186
/****************************************************************************
4187
Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4188
****************************************************************************/
4190
WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4194
dump_a_printer(printer, level);
4200
* Update the changestamp. Emperical tests show that the
4201
* ChangeID is always updated,but c_setprinter is
4202
* global spooler variable (not per printer).
4205
/* ChangeID **must** be increasing over the lifetime
4206
of client's spoolss service in order for the
4207
client's cache to show updates */
4209
printer->info_2->changeid = rev_changeid();
4212
* Because one day someone will ask:
4213
* NT->NT An admin connection to a remote
4214
* printer show changes imeediately in
4215
* the properities dialog
4217
* A non-admin connection will only show the
4218
* changes after viewing the properites page
4219
* 2 times. Seems to be related to a
4220
* race condition in the client between the spooler
4221
* updating the local cache and the Explorer.exe GUI
4222
* actually displaying the properties.
4224
* This is fixed in Win2k. admin/non-admin
4225
* connections both display changes immediately.
4230
result=update_a_printer_2(printer->info_2);
4234
result=WERR_UNKNOWN_LEVEL;
4241
/****************************************************************************
4242
Initialize printer devmode & data with previously saved driver init values.
4243
****************************************************************************/
4245
static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4250
NT_PRINTER_INFO_LEVEL_2 info;
4256
* Delete any printer data 'values' already set. When called for driver
4257
* replace, there will generally be some, but during an add printer, there
4258
* should not be any (if there are delete them).
4261
if ( info_ptr->data )
4262
delete_all_printer_data( info_ptr, "" );
4264
if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4265
info_ptr->drivername) < 0) {
4269
dbuf = tdb_fetch_bystring(tdb_drivers, key);
4272
* When changing to a driver that has no init info in the tdb, remove
4273
* the previous drivers init info and leave the new on blank.
4275
free_nt_devicemode(&info_ptr->devmode);
4282
* Get the saved DEVMODE..
4285
len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4288
* The saved DEVMODE contains the devicename from the printer used during
4289
* the initialization save. Change it to reflect the new printer.
4292
if ( info.devmode ) {
4293
ZERO_STRUCT(info.devmode->devicename);
4294
fstrcpy(info.devmode->devicename, info_ptr->printername);
4298
* NT/2k does not change out the entire DeviceMode of a printer
4299
* when changing the driver. Only the driverextra, private, &
4300
* driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4302
* Later examination revealed that Windows NT/2k does reset the
4303
* the printer's device mode, bit **only** when you change a
4304
* property of the device mode such as the page orientation.
4309
/* Bind the saved DEVMODE to the new the printer */
4311
free_nt_devicemode(&info_ptr->devmode);
4312
info_ptr->devmode = info.devmode;
4314
DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4315
info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4317
/* Add the printer data 'values' to the new printer */
4319
if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4320
DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4324
len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4326
SAFE_FREE(dbuf.dptr);
4331
/****************************************************************************
4332
Initialize printer devmode & data with previously saved driver init values.
4333
When a printer is created using AddPrinter, the drivername bound to the
4334
printer is used to lookup previously saved driver initialization info, which
4335
is bound to the new printer.
4336
****************************************************************************/
4338
bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4340
bool result = False;
4344
result = set_driver_init_2(printer->info_2);
4348
DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4356
/****************************************************************************
4357
Delete driver init data stored for a specified driver
4358
****************************************************************************/
4360
bool del_driver_init(const char *drivername)
4365
if (!drivername || !*drivername) {
4366
DEBUG(3,("del_driver_init: No drivername specified!\n"));
4370
if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4374
DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4377
ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4382
/****************************************************************************
4383
Pack up the DEVMODE and values for a printer into a 'driver init' entry
4384
in the tdb. Note: this is different from the driver entry and the printer
4385
entry. There should be a single driver init entry for each driver regardless
4386
of whether it was installed from NT or 2K. Technically, they should be
4387
different, but they work out to the same struct.
4388
****************************************************************************/
4390
static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4394
int buflen, len, ret;
4403
len += pack_devicemode(info->devmode, buf+len, buflen-len);
4405
retlen = pack_values( info->data, buf+len, buflen-len );
4413
buf = (uint8 *)SMB_REALLOC(buf, len);
4415
DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4424
if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4432
ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4436
DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4440
DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4441
info->sharename, info->drivername));
4446
/****************************************************************************
4447
Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4448
****************************************************************************/
4450
static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4454
dump_a_printer(printer, level);
4458
result = update_driver_init_2(printer->info_2);
4468
/****************************************************************************
4469
Convert the printer data value, a REG_BINARY array, into an initialization
4470
DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4471
got to keep the endians happy :).
4472
****************************************************************************/
4474
static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
4475
const uint8_t *data, uint32_t data_len)
4477
struct spoolss_DeviceMode devmode;
4478
enum ndr_err_code ndr_err;
4481
ZERO_STRUCT(devmode);
4483
blob = data_blob_const(data, data_len);
4485
ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
4486
(ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4487
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4488
DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4492
return convert_devicemode("", &devmode, &nt_devmode);
4495
/****************************************************************************
4496
Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4498
1. Use the driver's config DLL to this UNC printername and:
4499
a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4500
b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4501
2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4503
The last step triggers saving the "driver initialization" information for
4504
this printer into the tdb. Later, new printers that use this driver will
4505
have this initialization information bound to them. This simulates the
4506
driver initialization, as if it had run on the Samba server (as it would
4509
The Win32 client side code requirement sucks! But until we can run arbitrary
4510
Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4512
It would have been easier to use SetPrinter because all the UNMARSHALLING of
4513
the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4514
about it and you will realize why. JRR 010720
4515
****************************************************************************/
4517
static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4519
WERROR status = WERR_OK;
4520
TALLOC_CTX *ctx = NULL;
4521
NT_DEVICEMODE *nt_devmode = NULL;
4522
NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4525
* When the DEVMODE is already set on the printer, don't try to unpack it.
4527
DEBUG(8,("save_driver_init_2: Enter...\n"));
4529
if ( !printer->info_2->devmode && data_len ) {
4531
* Set devmode on printer info, so entire printer initialization can be
4535
if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4538
if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4539
status = WERR_NOMEM;
4543
ZERO_STRUCTP(nt_devmode);
4546
* The DEVMODE is held in the 'data' component of the param in raw binary.
4547
* Convert it to to a devmode structure
4549
if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4550
DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4551
status = WERR_INVALID_PARAM;
4555
printer->info_2->devmode = nt_devmode;
4559
* Pack up and add (or update) the DEVMODE and any current printer data to
4560
* a 'driver init' element in the tdb
4564
if ( update_driver_init(printer, 2) != 0 ) {
4565
DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4566
status = WERR_NOMEM;
4571
* If driver initialization info was successfully saved, set the current
4572
* printer to match it. This allows initialization of the current printer
4573
* as well as the driver.
4575
status = mod_a_printer(printer, 2);
4576
if (!W_ERROR_IS_OK(status)) {
4577
DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4578
printer->info_2->printername));
4582
talloc_destroy(ctx);
4583
free_nt_devicemode( &nt_devmode );
4585
printer->info_2->devmode = tmp_devmode;
4590
/****************************************************************************
4591
Update the driver init info (DEVMODE and specifics) for a printer
4592
****************************************************************************/
4594
WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4596
WERROR status = WERR_OK;
4600
status = save_driver_init_2( printer, data, data_len );
4603
status = WERR_UNKNOWN_LEVEL;
4610
/****************************************************************************
4611
Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4613
Previously the code had a memory allocation problem because it always
4614
used the TALLOC_CTX from the Printer_entry*. This context lasts
4615
as a long as the original handle is open. So if the client made a lot
4616
of getprinter[data]() calls, the memory usage would climb. Now we use
4617
a short lived TALLOC_CTX for printer_info_2 objects returned. We
4618
still use the Printer_entry->ctx for maintaining the cache copy though
4619
since that object must live as long as the handle by definition.
4622
****************************************************************************/
4624
static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4625
const char *sharename, bool get_loc_com)
4630
DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4632
if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4633
DEBUG(0,("get_a_printer: talloc() fail.\n"));
4639
if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4640
DEBUG(0,("get_a_printer: talloc() fail.\n"));
4641
TALLOC_FREE( *pp_printer );
4646
fstrcpy( servername, print_hnd->servername );
4648
fstrcpy( servername, "%L" );
4649
standard_sub_basic( "", "", servername,
4650
sizeof(servername)-1 );
4653
result = get_a_printer_2( (*pp_printer)->info_2,
4654
servername, sharename, get_loc_com);
4656
/* we have a new printer now. Save it with this handle */
4658
if ( !W_ERROR_IS_OK(result) ) {
4659
TALLOC_FREE( *pp_printer );
4660
DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4661
sharename, (unsigned int)level, win_errstr(result)));
4665
dump_a_printer( *pp_printer, level);
4670
TALLOC_FREE( *pp_printer );
4671
return WERR_UNKNOWN_LEVEL;
4677
WERROR get_a_printer( Printer_entry *print_hnd,
4678
NT_PRINTER_INFO_LEVEL **pp_printer,
4680
const char *sharename)
4682
return get_a_printer_internal(print_hnd, pp_printer, level,
4686
WERROR get_a_printer_search( Printer_entry *print_hnd,
4687
NT_PRINTER_INFO_LEVEL **pp_printer,
4689
const char *sharename)
4691
return get_a_printer_internal(print_hnd, pp_printer, level,
4695
/****************************************************************************
4696
Deletes a NT_PRINTER_INFO_LEVEL struct.
4697
****************************************************************************/
4699
uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4701
NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4708
if ( printer->info_2 )
4709
free_nt_printer_info_level_2(&printer->info_2);
4713
DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4717
TALLOC_FREE(*pp_printer);
4722
/****************************************************************************
4723
****************************************************************************/
4724
uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4727
DEBUG(104,("adding a printer at level [%d]\n", level));
4728
dump_a_printer_driver(driver, level);
4732
result=add_a_printer_driver_3(driver.info_3);
4736
result=add_a_printer_driver_6(driver.info_6);
4746
/****************************************************************************
4747
****************************************************************************/
4749
WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
4750
const char *drivername, const char *architecture,
4757
/* Sometime we just want any version of the driver */
4759
if ( version == DRIVER_ANY_VERSION ) {
4760
/* look for Win2k first and then for NT4 */
4761
result = get_a_printer_driver_3(&driver->info_3, drivername,
4764
if ( !W_ERROR_IS_OK(result) ) {
4765
result = get_a_printer_driver_3( &driver->info_3,
4766
drivername, architecture, 2 );
4769
result = get_a_printer_driver_3(&driver->info_3, drivername,
4770
architecture, version);
4779
if (W_ERROR_IS_OK(result))
4780
dump_a_printer_driver(*driver, level);
4785
/****************************************************************************
4786
****************************************************************************/
4787
uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4794
NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4795
if (driver.info_3 != NULL)
4797
info3=driver.info_3;
4798
SAFE_FREE(info3->dependentfiles);
4799
ZERO_STRUCTP(info3);
4809
NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4810
if (driver.info_6 != NULL) {
4811
info6=driver.info_6;
4812
SAFE_FREE(info6->dependentfiles);
4813
SAFE_FREE(info6->previousnames);
4814
ZERO_STRUCTP(info6);
4830
/****************************************************************************
4831
Determine whether or not a particular driver is currently assigned
4833
****************************************************************************/
4835
bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4838
int n_services = lp_numservices();
4839
NT_PRINTER_INFO_LEVEL *printer = NULL;
4840
bool in_use = False;
4845
DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4847
/* loop through the printers.tdb and check for the drivername */
4849
for (snum=0; snum<n_services && !in_use; snum++) {
4850
if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4853
if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4856
if ( strequal(info_3->name, printer->info_2->drivername) )
4859
free_a_printer( &printer, 2 );
4862
DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4865
NT_PRINTER_DRIVER_INFO_LEVEL d;
4868
DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4870
/* we can still remove the driver if there is one of
4871
"Windows NT x86" version 2 or 3 left */
4873
if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4874
werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4877
switch ( info_3->cversion ) {
4879
werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4882
werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4885
DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4887
werr = WERR_UNKNOWN_PRINTER_DRIVER;
4892
/* now check the error code */
4894
if ( W_ERROR_IS_OK(werr) ) {
4895
/* it's ok to remove the driver, we have other architctures left */
4897
free_a_printer_driver( d, 3 );
4901
/* report that the driver is not in use by default */
4907
/**********************************************************************
4908
Check to see if a ogiven file is in use by *info
4909
*********************************************************************/
4911
static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4918
/* mz: skip files that are in the list but already deleted */
4919
if (!file || !file[0]) {
4923
if ( strequal(file, info->driverpath) )
4926
if ( strequal(file, info->datafile) )
4929
if ( strequal(file, info->configfile) )
4932
if ( strequal(file, info->helpfile) )
4935
/* see of there are any dependent files to examine */
4937
if ( !info->dependentfiles )
4940
while ( *info->dependentfiles[i] ) {
4941
if ( strequal(file, info->dependentfiles[i]) )
4950
/**********************************************************************
4951
Utility function to remove the dependent file pointed to by the
4952
input parameter from the list
4953
*********************************************************************/
4955
static void trim_dependent_file( fstring files[], int idx )
4958
/* bump everything down a slot */
4960
while( *files[idx+1] ) {
4961
fstrcpy( files[idx], files[idx+1] );
4970
/**********************************************************************
4971
Check if any of the files used by src are also used by drv
4972
*********************************************************************/
4974
static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4975
NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4977
bool in_use = False;
4983
/* check each file. Remove it from the src structure if it overlaps */
4985
if ( drv_file_in_use(src->driverpath, drv) ) {
4987
DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4988
fstrcpy( src->driverpath, "" );
4991
if ( drv_file_in_use(src->datafile, drv) ) {
4993
DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4994
fstrcpy( src->datafile, "" );
4997
if ( drv_file_in_use(src->configfile, drv) ) {
4999
DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5000
fstrcpy( src->configfile, "" );
5003
if ( drv_file_in_use(src->helpfile, drv) ) {
5005
DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5006
fstrcpy( src->helpfile, "" );
5009
/* are there any dependentfiles to examine? */
5011
if ( !src->dependentfiles )
5014
while ( *src->dependentfiles[i] ) {
5015
if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5017
DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5018
trim_dependent_file( src->dependentfiles, i );
5026
/****************************************************************************
5027
Determine whether or not a particular driver files are currently being
5028
used by any other driver.
5030
Return value is True if any files were in use by other drivers
5031
and False otherwise.
5033
Upon return, *info has been modified to only contain the driver files
5034
which are not in use
5038
This needs to check all drivers to ensure that all files in use
5039
have been removed from *info, not just the ones in the first
5041
****************************************************************************/
5043
bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5048
fstring *list = NULL;
5049
NT_PRINTER_DRIVER_INFO_LEVEL driver;
5050
bool in_use = false;
5055
version = info->cversion;
5057
/* loop over all driver versions */
5059
DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5061
/* get the list of drivers */
5064
ndrivers = get_ntdrivers(&list, info->environment, version);
5066
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5067
ndrivers, info->environment, version));
5069
/* check each driver for overlap in files */
5071
for (i=0; i<ndrivers; i++) {
5072
DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5074
ZERO_STRUCT(driver);
5076
if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5081
/* check if d2 uses any files from d1 */
5082
/* only if this is a different driver than the one being deleted */
5084
if ( !strequal(info->name, driver.info_3->name) ) {
5085
if ( trim_overlap_drv_files(info, driver.info_3) ) {
5086
/* mz: Do not instantly return -
5087
* we need to ensure this file isn't
5088
* also in use by other drivers. */
5093
free_a_printer_driver(driver, 3);
5098
DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5100
driver.info_3 = info;
5102
if ( DEBUGLEVEL >= 20 )
5103
dump_a_printer_driver( driver, 3 );
5108
/****************************************************************************
5109
Actually delete the driver files. Make sure that
5110
printer_driver_files_in_use() return False before calling
5112
****************************************************************************/
5114
static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5115
NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
5120
connection_struct *conn;
5124
fstring printdollar;
5125
int printdollar_snum;
5131
DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5133
fstrcpy(printdollar, "print$");
5135
printdollar_snum = find_service(printdollar);
5136
if (printdollar_snum == -1) {
5140
nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5141
lp_pathname(printdollar_snum),
5142
rpc_pipe->server_info, &oldcwd);
5143
if (!NT_STATUS_IS_OK(nt_status)) {
5144
DEBUG(0,("delete_driver_files: create_conn_struct "
5145
"returned %s\n", nt_errstr(nt_status)));
5149
if ( !CAN_WRITE(conn) ) {
5150
DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5154
/* now delete the files; must strip the '\print$' string from
5157
if ( *info_3->driverpath ) {
5158
if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5160
driver_unix_convert(conn,file,&st);
5161
DEBUG(10,("deleting driverfile [%s]\n", s));
5162
unlink_internals(conn, NULL, 0, file, False);
5166
if ( *info_3->configfile ) {
5167
if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5169
driver_unix_convert(conn,file,&st);
5170
DEBUG(10,("deleting configfile [%s]\n", s));
5171
unlink_internals(conn, NULL, 0, file, False);
5175
if ( *info_3->datafile ) {
5176
if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5178
driver_unix_convert(conn,file,&st);
5179
DEBUG(10,("deleting datafile [%s]\n", s));
5180
unlink_internals(conn, NULL, 0, file, False);
5184
if ( *info_3->helpfile ) {
5185
if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5187
driver_unix_convert(conn,file,&st);
5188
DEBUG(10,("deleting helpfile [%s]\n", s));
5189
unlink_internals(conn, NULL, 0, file, False);
5193
/* check if we are done removing files */
5195
if ( info_3->dependentfiles ) {
5196
while ( info_3->dependentfiles[i][0] ) {
5199
/* bypass the "\print$" portion of the path */
5201
if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5203
driver_unix_convert(conn,file,&st);
5204
DEBUG(10,("deleting dependent file [%s]\n", file));
5205
unlink_internals(conn, NULL, 0, file, False);
5217
vfs_ChDir(conn, oldcwd);
5218
conn_free_internal(conn);
5223
/****************************************************************************
5224
Remove a printer driver from the TDB. This assumes that the the driver was
5225
previously looked up.
5226
***************************************************************************/
5228
WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5229
NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3,
5230
uint32 version, bool delete_files )
5235
NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5237
/* delete the tdb data first */
5239
arch = get_short_archi(info_3->environment);
5241
return WERR_UNKNOWN_PRINTER_DRIVER;
5243
if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5244
arch, version, info_3->name) < 0) {
5248
DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5249
key, delete_files ? "TRUE" : "FALSE" ));
5251
ctr.info_3 = info_3;
5252
dump_a_printer_driver( ctr, 3 );
5254
/* check if the driver actually exists for this environment */
5256
dbuf = tdb_fetch_bystring( tdb_drivers, key );
5258
DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5260
return WERR_UNKNOWN_PRINTER_DRIVER;
5263
SAFE_FREE( dbuf.dptr );
5265
/* ok... the driver exists so the delete should return success */
5267
if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5268
DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5270
return WERR_ACCESS_DENIED;
5274
* now delete any associated files if delete_files == True
5275
* even if this part failes, we return succes because the
5276
* driver doesn not exist any more
5280
delete_driver_files(rpc_pipe, info_3);
5282
DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5288
/****************************************************************************
5289
Store a security desc for a printer.
5290
****************************************************************************/
5292
WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5294
SEC_DESC_BUF *new_secdesc_ctr = NULL;
5295
SEC_DESC_BUF *old_secdesc_ctr = NULL;
5296
TALLOC_CTX *mem_ctx = NULL;
5303
mem_ctx = talloc_init("nt_printing_setsec");
5304
if (mem_ctx == NULL)
5307
/* The old owner and group sids of the security descriptor are not
5308
present when new ACEs are added or removed by changing printer
5309
permissions through NT. If they are NULL in the new security
5310
descriptor then copy them over from the old one. */
5312
if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5313
DOM_SID *owner_sid, *group_sid;
5314
SEC_ACL *dacl, *sacl;
5315
SEC_DESC *psd = NULL;
5318
if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5319
status = WERR_NOMEM;
5323
/* Pick out correct owner and group sids */
5325
owner_sid = secdesc_ctr->sd->owner_sid ?
5326
secdesc_ctr->sd->owner_sid :
5327
old_secdesc_ctr->sd->owner_sid;
5329
group_sid = secdesc_ctr->sd->group_sid ?
5330
secdesc_ctr->sd->group_sid :
5331
old_secdesc_ctr->sd->group_sid;
5333
dacl = secdesc_ctr->sd->dacl ?
5334
secdesc_ctr->sd->dacl :
5335
old_secdesc_ctr->sd->dacl;
5337
sacl = secdesc_ctr->sd->sacl ?
5338
secdesc_ctr->sd->sacl :
5339
old_secdesc_ctr->sd->sacl;
5341
/* Make a deep copy of the security descriptor */
5343
psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5344
owner_sid, group_sid,
5350
status = WERR_NOMEM;
5354
new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5357
if (!new_secdesc_ctr) {
5358
new_secdesc_ctr = secdesc_ctr;
5361
/* Store the security descriptor in a tdb */
5363
nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5364
&blob.data, &blob.length);
5365
if (!NT_STATUS_IS_OK(nt_status)) {
5366
status = ntstatus_to_werror(nt_status);
5370
kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5372
dbuf.dptr = (unsigned char *)blob.data;
5373
dbuf.dsize = blob.length;
5375
if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5378
DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5379
status = WERR_BADFUNC;
5382
/* Free malloc'ed memory */
5383
talloc_free(blob.data);
5388
talloc_destroy(mem_ctx);
5392
/****************************************************************************
5393
Construct a default security descriptor buffer for a printer.
5394
****************************************************************************/
5396
static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5398
SEC_ACE ace[5]; /* max number of ace entries */
5401
SEC_ACL *psa = NULL;
5402
SEC_DESC_BUF *sdb = NULL;
5403
SEC_DESC *psd = NULL;
5407
/* Create an ACE where Everyone is allowed to print */
5409
sa = PRINTER_ACE_PRINT;
5410
init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5411
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5413
/* Add the domain admins group if we are a DC */
5416
DOM_SID domadmins_sid;
5418
sid_copy(&domadmins_sid, get_global_sam_sid());
5419
sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5421
sa = PRINTER_ACE_FULL_CONTROL;
5422
init_sec_ace(&ace[i++], &domadmins_sid,
5423
SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5424
SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5425
init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5426
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5428
else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5429
sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5431
sa = PRINTER_ACE_FULL_CONTROL;
5432
init_sec_ace(&ace[i++], &adm_sid,
5433
SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5434
SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5435
init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5436
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5439
/* add BUILTIN\Administrators as FULL CONTROL */
5441
sa = PRINTER_ACE_FULL_CONTROL;
5442
init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5443
SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5444
SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5445
init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5446
SEC_ACE_TYPE_ACCESS_ALLOWED,
5447
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5449
/* Make the security descriptor owned by the BUILTIN\Administrators */
5451
/* The ACL revision number in rpc_secdesc.h differs from the one
5452
created by NT when setting ACE entries in printer
5453
descriptors. NT4 complains about the property being edited by a
5456
if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5457
psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5458
&global_sid_Builtin_Administrators,
5459
&global_sid_Builtin_Administrators,
5460
NULL, psa, &sd_size);
5464
DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5468
sdb = make_sec_desc_buf(ctx, sd_size, psd);
5470
DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5471
(unsigned int)sd_size));
5476
/****************************************************************************
5477
Get a security desc for a printer.
5478
****************************************************************************/
5480
bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5488
if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5489
sharename = temp + 1;
5492
/* Fetch security descriptor from tdb */
5494
kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5496
dbuf = tdb_fetch(tdb_printers, kbuf);
5499
status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5501
SAFE_FREE(dbuf.dptr);
5503
if (NT_STATUS_IS_OK(status)) {
5508
*secdesc_ctr = construct_default_printer_sdb(ctx);
5509
if (!*secdesc_ctr) {
5513
status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5514
&blob.data, &blob.length);
5515
if (NT_STATUS_IS_OK(status)) {
5516
dbuf.dptr = (unsigned char *)blob.data;
5517
dbuf.dsize = blob.length;
5518
tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5519
talloc_free(blob.data);
5522
/* If security descriptor is owned by S-1-1-0 and winbindd is up,
5523
this security descriptor has been created when winbindd was
5524
down. Take ownership of security descriptor. */
5526
if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5529
/* Change sd owner to workgroup administrator */
5531
if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5532
SEC_DESC_BUF *new_secdesc_ctr = NULL;
5533
SEC_DESC *psd = NULL;
5538
sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5540
psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5542
(*secdesc_ctr)->sd->group_sid,
5543
(*secdesc_ctr)->sd->sacl,
5544
(*secdesc_ctr)->sd->dacl,
5551
new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5552
if (!new_secdesc_ctr) {
5556
/* Swap with other one */
5558
*secdesc_ctr = new_secdesc_ctr;
5562
nt_printing_setsec(sharename, *secdesc_ctr);
5566
if (DEBUGLEVEL >= 10) {
5567
SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5570
DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5571
sharename, the_acl->num_aces));
5573
for (i = 0; i < the_acl->num_aces; i++) {
5574
DEBUG(10, ("%s %d %d 0x%08x\n",
5575
sid_string_dbg(&the_acl->aces[i].trustee),
5576
the_acl->aces[i].type, the_acl->aces[i].flags,
5577
the_acl->aces[i].access_mask));
5586
1: level not implemented
5587
2: file doesn't exist
5588
3: can't allocate memory
5589
4: can't free memory
5590
5: non existant struct
5594
A printer and a printer driver are 2 different things.
5595
NT manages them separatelly, Samba does the same.
5596
Why ? Simply because it's easier and it makes sense !
5598
Now explanation: You have 3 printers behind your samba server,
5599
2 of them are the same make and model (laser A and B). But laser B
5600
has an 3000 sheet feeder and laser A doesn't such an option.
5601
Your third printer is an old dot-matrix model for the accounting :-).
5603
If the /usr/local/samba/lib directory (default dir), you will have
5604
5 files to describe all of this.
5606
3 files for the printers (1 by printer):
5609
NTprinter_accounting
5610
2 files for the drivers (1 for the laser and 1 for the dot matrix)
5611
NTdriver_printer model X
5612
NTdriver_printer model Y
5614
jfm: I should use this comment for the text file to explain
5615
same thing for the forms BTW.
5616
Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5620
/* Convert generic access rights to printer object specific access rights.
5621
It turns out that NT4 security descriptors use generic access rights and
5622
NT5 the object specific ones. */
5624
void map_printer_permissions(SEC_DESC *sd)
5628
for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5629
se_map_generic(&sd->dacl->aces[i].access_mask,
5630
&printer_generic_mapping);
5634
void map_job_permissions(SEC_DESC *sd)
5638
for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5639
se_map_generic(&sd->dacl->aces[i].access_mask,
5640
&job_generic_mapping);
5645
/****************************************************************************
5646
Check a user has permissions to perform the given operation. We use the
5647
permission constants defined in include/rpc_spoolss.h to check the various
5648
actions we perform when checking printer access.
5650
PRINTER_ACCESS_ADMINISTER:
5651
print_queue_pause, print_queue_resume, update_printer_sec,
5652
update_printer, spoolss_addprinterex_level_2,
5653
_spoolss_setprinterdata
5658
JOB_ACCESS_ADMINISTER:
5659
print_job_delete, print_job_pause, print_job_resume,
5662
Try access control in the following order (for performance reasons):
5663
1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5664
2) check security descriptor (bit comparisons in memory)
5665
3) "printer admins" (may result in numerous calls to winbind)
5667
****************************************************************************/
5668
bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5671
SEC_DESC_BUF *secdesc = NULL;
5672
uint32 access_granted;
5675
TALLOC_CTX *mem_ctx = NULL;
5676
SE_PRIV se_printop = SE_PRINT_OPERATOR;
5678
/* If user is NULL then use the current_user structure */
5680
/* Always allow root or SE_PRINT_OPERATROR to do anything */
5682
if (server_info->utok.uid == sec_initial_uid()
5683
|| user_has_privileges(server_info->ptok, &se_printop ) ) {
5687
/* Get printer name */
5689
pname = PRINTERNAME(snum);
5691
if (!pname || !*pname) {
5696
/* Get printer security descriptor */
5698
if(!(mem_ctx = talloc_init("print_access_check"))) {
5703
if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5704
talloc_destroy(mem_ctx);
5709
if (access_type == JOB_ACCESS_ADMINISTER) {
5710
SEC_DESC_BUF *parent_secdesc = secdesc;
5712
/* Create a child security descriptor to check permissions
5713
against. This is because print jobs are child objects
5714
objects of a printer. */
5716
status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5718
if (!NT_STATUS_IS_OK(status)) {
5719
talloc_destroy(mem_ctx);
5720
errno = map_errno_from_nt_status(status);
5724
map_job_permissions(secdesc->sd);
5726
map_printer_permissions(secdesc->sd);
5730
status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5733
DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5735
/* see if we need to try the printer admin list */
5737
if (!NT_STATUS_IS_OK(status) &&
5738
(token_contains_name_in_list(uidtoname(server_info->utok.uid),
5739
NULL, NULL, server_info->ptok,
5740
lp_printer_admin(snum)))) {
5741
talloc_destroy(mem_ctx);
5745
talloc_destroy(mem_ctx);
5747
if (!NT_STATUS_IS_OK(status)) {
5751
return NT_STATUS_IS_OK(status);
5754
/****************************************************************************
5755
Check the time parameters allow a print operation.
5756
*****************************************************************************/
5758
bool print_time_access_check(const char *servicename)
5760
NT_PRINTER_INFO_LEVEL *printer = NULL;
5762
time_t now = time(NULL);
5766
if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5769
if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5773
mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5775
if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5778
free_a_printer(&printer, 2);
5786
/****************************************************************************
5787
Fill in the servername sent in the _spoolss_open_printer_ex() call
5788
****************************************************************************/
5790
char* get_server_name( Printer_entry *printer )
5792
return printer->servername;