~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/printing/nt_printing.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Unix SMB/CIFS implementation.
 
3
 *  RPC Pipe client / server routines
 
4
 *  Copyright (C) Andrew Tridgell              1992-2000,
 
5
 *  Copyright (C) Jean François Micouleau      1998-2000.
 
6
 *  Copyright (C) Gerald Carter                2002-2005.
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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/>.
 
20
 */
 
21
 
 
22
#include "includes.h"
 
23
 
 
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 */
 
27
 
 
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"
 
34
 
 
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 */
 
40
 
 
41
/* Map generic permissions to printer object specific permissions */
 
42
 
 
43
const struct generic_mapping printer_generic_mapping = {
 
44
        PRINTER_READ,
 
45
        PRINTER_WRITE,
 
46
        PRINTER_EXECUTE,
 
47
        PRINTER_ALL_ACCESS
 
48
};
 
49
 
 
50
const struct standard_mapping printer_std_mapping = {
 
51
        PRINTER_READ,
 
52
        PRINTER_WRITE,
 
53
        PRINTER_EXECUTE,
 
54
        PRINTER_ALL_ACCESS
 
55
};
 
56
 
 
57
/* Map generic permissions to print server object specific permissions */
 
58
 
 
59
const struct generic_mapping printserver_generic_mapping = {
 
60
        SERVER_READ,
 
61
        SERVER_WRITE,
 
62
        SERVER_EXECUTE,
 
63
        SERVER_ALL_ACCESS
 
64
};
 
65
 
 
66
const struct generic_mapping printserver_std_mapping = {
 
67
        SERVER_READ,
 
68
        SERVER_WRITE,
 
69
        SERVER_EXECUTE,
 
70
        SERVER_ALL_ACCESS
 
71
};
 
72
 
 
73
/* Map generic permissions to job object specific permissions */
 
74
 
 
75
const struct generic_mapping job_generic_mapping = {
 
76
        JOB_READ,
 
77
        JOB_WRITE,
 
78
        JOB_EXECUTE,
 
79
        JOB_ALL_ACCESS
 
80
};
 
81
 
 
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}
 
205
};
 
206
 
 
207
static const struct print_architecture_table_node archi_table[]= {
 
208
 
 
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 },
 
216
        {NULL,                   "",            -1 }
 
217
};
 
218
 
 
219
 
 
220
/****************************************************************************
 
221
 generate a new TDB_DATA key for storing a printer
 
222
****************************************************************************/
 
223
 
 
224
static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
 
225
{
 
226
        fstring share;
 
227
        char *keystr = NULL;
 
228
        TDB_DATA key;
 
229
 
 
230
        fstrcpy(share, sharename);
 
231
        strlower_m(share);
 
232
 
 
233
        keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
 
234
        key = string_term_tdb_data(keystr ? keystr : "");
 
235
 
 
236
        return key;
 
237
}
 
238
 
 
239
/****************************************************************************
 
240
 generate a new TDB_DATA key for storing a printer security descriptor
 
241
****************************************************************************/
 
242
 
 
243
static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
 
244
                                        const char* sharename  )
 
245
{
 
246
        fstring share;
 
247
        char *keystr = NULL;
 
248
        TDB_DATA key;
 
249
 
 
250
        fstrcpy(share, sharename );
 
251
        strlower_m(share);
 
252
 
 
253
        keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
 
254
        key = string_term_tdb_data(keystr ? keystr : "");
 
255
 
 
256
        return key;
 
257
}
 
258
 
 
259
/****************************************************************************
 
260
****************************************************************************/
 
261
 
 
262
static bool upgrade_to_version_3(void)
 
263
{
 
264
        TDB_DATA kbuf, newkey, dbuf;
 
265
 
 
266
        DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
 
267
 
 
268
        for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
 
269
                        newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
 
270
 
 
271
                dbuf = tdb_fetch(tdb_drivers, kbuf);
 
272
 
 
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)));
 
278
                                return False;
 
279
                        }
 
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)));
 
283
                                return False;
 
284
                        }
 
285
                }
 
286
 
 
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)));
 
292
                                return False;
 
293
                        }
 
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)));
 
297
                                return False;
 
298
                        }
 
299
                }
 
300
 
 
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)));
 
306
                                return False;
 
307
                        }
 
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)));
 
311
                                return False;
 
312
                        }
 
313
                }
 
314
 
 
315
                SAFE_FREE(dbuf.dptr);
 
316
        }
 
317
 
 
318
        return True;
 
319
}
 
320
 
 
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
*******************************************************************/
 
328
 
 
329
static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
 
330
                            TDB_DATA data, void *state )
 
331
{
 
332
        NTSTATUS status;
 
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;
 
337
        int result, i;
 
338
        uint32 sd_size;
 
339
        size_t size_new_sec;
 
340
 
 
341
        if (!data.dptr || data.dsize == 0) {
 
342
                return 0;
 
343
        }
 
344
 
 
345
        if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
 
346
                return 0;
 
347
        }
 
348
 
 
349
        /* upgrade the security descriptor */
 
350
 
 
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 );
 
357
                return 0;
 
358
        }
 
359
 
 
360
        if (!sd_orig) {
 
361
                return 0;
 
362
        }
 
363
        sec = sd_orig->sd;
 
364
 
 
365
        /* is this even valid? */
 
366
 
 
367
        if ( !sec->dacl ) {
 
368
                return 0;
 
369
        }
 
370
 
 
371
        /* update access masks */
 
372
 
 
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;
 
377
                                break;
 
378
 
 
379
                        case GENERIC_ALL_ACCESS:
 
380
                                sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
 
381
                                break;
 
382
 
 
383
                        case READ_CONTROL_ACCESS:
 
384
                                sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
 
385
 
 
386
                        default:        /* no change */
 
387
                                break;
 
388
                }
 
389
        }
 
390
 
 
391
        /* create a new SEC_DESC with the appropriate owner and group SIDs */
 
392
 
 
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 );
 
397
        if (!new_sec) {
 
398
                return 0;
 
399
        }
 
400
        sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
 
401
        if (!sd_new) {
 
402
                return 0;
 
403
        }
 
404
 
 
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 ));
 
407
                return 0;
 
408
        }
 
409
 
 
410
        /* store it back */
 
411
 
 
412
        sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0)
 
413
                + sizeof(SEC_DESC_BUF);
 
414
 
 
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 ));
 
418
                return 0;
 
419
        }
 
420
 
 
421
        result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
 
422
 
 
423
        /* 0 to continue and non-zero to stop traversal */
 
424
 
 
425
        return (result == -1);
 
426
}
 
427
 
 
428
/*******************************************************************
 
429
*******************************************************************/
 
430
 
 
431
static bool upgrade_to_version_4(void)
 
432
{
 
433
        TALLOC_CTX *ctx;
 
434
        int result;
 
435
 
 
436
        DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
 
437
 
 
438
        if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
 
439
                return False;
 
440
 
 
441
        result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
 
442
 
 
443
        talloc_destroy( ctx );
 
444
 
 
445
        return ( result != -1 );
 
446
}
 
447
 
 
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
*******************************************************************/
 
455
 
 
456
static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
 
457
                                  TDB_DATA data, void *state )
 
458
{
 
459
        TALLOC_CTX *ctx = talloc_tos();
 
460
        TDB_DATA new_key;
 
461
 
 
462
        if (!data.dptr || data.dsize == 0)
 
463
                return 0;
 
464
 
 
465
        /* upgrade printer records and security descriptors */
 
466
 
 
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) );
 
469
        }
 
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) );
 
472
        }
 
473
        else {
 
474
                /* ignore this record */
 
475
                return 0;
 
476
        }
 
477
 
 
478
        /* delete the original record and store under the normalized key */
 
479
 
 
480
        if ( tdb_delete( the_tdb, key ) != 0 ) {
 
481
                DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
 
482
                        key.dptr));
 
483
                return 1;
 
484
        }
 
485
 
 
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",
 
488
                        key.dptr));
 
489
                return 1;
 
490
        }
 
491
 
 
492
        return 0;
 
493
}
 
494
 
 
495
/*******************************************************************
 
496
*******************************************************************/
 
497
 
 
498
static bool upgrade_to_version_5(void)
 
499
{
 
500
        TALLOC_CTX *ctx;
 
501
        int result;
 
502
 
 
503
        DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
 
504
 
 
505
        if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
 
506
                return False;
 
507
 
 
508
        result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
 
509
 
 
510
        talloc_destroy( ctx );
 
511
 
 
512
        return ( result != -1 );
 
513
}
 
514
 
 
515
/****************************************************************************
 
516
 Open the NT printing tdbs. Done once before fork().
 
517
****************************************************************************/
 
518
 
 
519
bool nt_printing_init(struct messaging_context *msg_ctx)
 
520
{
 
521
        const char *vstring = "INFO/version";
 
522
        WERROR win_rc;
 
523
        int32 vers_id;
 
524
 
 
525
        if ( tdb_drivers && tdb_printers && tdb_forms )
 
526
                return True;
 
527
 
 
528
        if (tdb_drivers)
 
529
                tdb_close(tdb_drivers);
 
530
        tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 
531
        if (!tdb_drivers) {
 
532
                DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
 
533
                        state_path("ntdrivers.tdb"), strerror(errno) ));
 
534
                return False;
 
535
        }
 
536
 
 
537
        if (tdb_printers)
 
538
                tdb_close(tdb_printers);
 
539
        tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 
540
        if (!tdb_printers) {
 
541
                DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
 
542
                        state_path("ntprinters.tdb"), strerror(errno) ));
 
543
                return False;
 
544
        }
 
545
 
 
546
        if (tdb_forms)
 
547
                tdb_close(tdb_forms);
 
548
        tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 
549
        if (!tdb_forms) {
 
550
                DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
 
551
                        state_path("ntforms.tdb"), strerror(errno) ));
 
552
                return False;
 
553
        }
 
554
 
 
555
        /* handle a Samba upgrade */
 
556
 
 
557
        vers_id = tdb_fetch_int32(tdb_drivers, vstring);
 
558
        if (vers_id == -1) {
 
559
                DEBUG(10, ("Fresh database\n"));
 
560
                tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
 
561
                vers_id = NTDRIVERS_DATABASE_VERSION_5;
 
562
        }
 
563
 
 
564
        if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
 
565
 
 
566
                if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
 
567
                        if (!upgrade_to_version_3())
 
568
                                return False;
 
569
                        tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
 
570
                        vers_id = NTDRIVERS_DATABASE_VERSION_3;
 
571
                }
 
572
 
 
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;
 
578
                }
 
579
 
 
580
                if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
 
581
                        if ( !upgrade_to_version_4() )
 
582
                                return False;
 
583
                        tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
 
584
                        vers_id = NTDRIVERS_DATABASE_VERSION_4;
 
585
                }
 
586
 
 
587
                if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
 
588
                        if ( !upgrade_to_version_5() )
 
589
                                return False;
 
590
                        tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
 
591
                        vers_id = NTDRIVERS_DATABASE_VERSION_5;
 
592
                }
 
593
 
 
594
 
 
595
                if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
 
596
                        DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
 
597
                        return False;
 
598
                }
 
599
        }
 
600
 
 
601
        update_c_setprinter(True);
 
602
 
 
603
        /*
 
604
         * register callback to handle updating printers as new
 
605
         * drivers are installed
 
606
         */
 
607
 
 
608
        messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
 
609
                           do_drv_upgrade_printer);
 
610
 
 
611
        /*
 
612
         * register callback to handle updating printer data
 
613
         * when a driver is initialized
 
614
         */
 
615
 
 
616
        messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
 
617
                           reset_all_printerdata);
 
618
 
 
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() */
 
622
 
 
623
 
 
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)));
 
628
        }
 
629
 
 
630
        return True;
 
631
}
 
632
 
 
633
/*******************************************************************
 
634
 Function to allow filename parsing "the old way".
 
635
********************************************************************/
 
636
 
 
637
static char *driver_unix_convert(connection_struct *conn,
 
638
                const char *old_name,
 
639
                SMB_STRUCT_STAT *pst)
 
640
{
 
641
        TALLOC_CTX *ctx = talloc_tos();
 
642
        char *name = talloc_strdup(ctx, old_name);
 
643
        char *new_name = NULL;
 
644
 
 
645
        if (!name) {
 
646
                return NULL;
 
647
        }
 
648
        unix_format(name);
 
649
        name = unix_clean_name(ctx, name);
 
650
        if (!name) {
 
651
                return NULL;
 
652
        }
 
653
        trim_string(name,"/","/");
 
654
        unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
 
655
        return new_name;
 
656
}
 
657
 
 
658
/*******************************************************************
 
659
 tdb traversal function for counting printers.
 
660
********************************************************************/
 
661
 
 
662
static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
 
663
                                      TDB_DATA data, void *context)
 
664
{
 
665
        int *printer_count = (int*)context;
 
666
 
 
667
        if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
 
668
                (*printer_count)++;
 
669
                DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
 
670
        }
 
671
 
 
672
        return 0;
 
673
}
 
674
 
 
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
********************************************************************/
 
681
 
 
682
uint32 update_c_setprinter(bool initialize)
 
683
{
 
684
        int32 c_setprinter;
 
685
        int32 printer_count = 0;
 
686
 
 
687
        tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
 
688
 
 
689
        /* Traverse the tdb, counting the printers */
 
690
        tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
 
691
 
 
692
        /* If initializing, set c_setprinter to current printers count
 
693
         * otherwise, bump it by the current printer count
 
694
         */
 
695
        if (!initialize)
 
696
                c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
 
697
        else
 
698
                c_setprinter = printer_count;
 
699
 
 
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);
 
702
 
 
703
        tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
 
704
 
 
705
        return (uint32)c_setprinter;
 
706
}
 
707
 
 
708
/*******************************************************************
 
709
 Get the spooler global c_setprinter, accounting for initialization.
 
710
********************************************************************/
 
711
 
 
712
uint32 get_c_setprinter(void)
 
713
{
 
714
        int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
 
715
 
 
716
        if (c_setprinter == (int32)-1)
 
717
                c_setprinter = update_c_setprinter(True);
 
718
 
 
719
        DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
 
720
 
 
721
        return (uint32)c_setprinter;
 
722
}
 
723
 
 
724
/****************************************************************************
 
725
 Get builtin form struct list.
 
726
****************************************************************************/
 
727
 
 
728
int get_builtin_ntforms(nt_forms_struct **list)
 
729
{
 
730
        *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
 
731
        if (!*list) {
 
732
                return 0;
 
733
        }
 
734
        return ARRAY_SIZE(default_forms);
 
735
}
 
736
 
 
737
/****************************************************************************
 
738
 get a builtin form struct
 
739
****************************************************************************/
 
740
 
 
741
bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
 
742
{
 
743
        int i;
 
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));
 
749
                        return true;
 
750
                }
 
751
        }
 
752
 
 
753
        return false;
 
754
}
 
755
 
 
756
/****************************************************************************
 
757
 get a form struct list.
 
758
****************************************************************************/
 
759
 
 
760
int get_ntforms(nt_forms_struct **list)
 
761
{
 
762
        TDB_DATA kbuf, newkey, dbuf;
 
763
        nt_forms_struct form;
 
764
        int ret;
 
765
        int i;
 
766
        int n = 0;
 
767
 
 
768
        *list = NULL;
 
769
 
 
770
        for (kbuf = tdb_firstkey(tdb_forms);
 
771
             kbuf.dptr;
 
772
             newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
 
773
        {
 
774
                if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
 
775
                        continue;
 
776
 
 
777
                dbuf = tdb_fetch(tdb_forms, kbuf);
 
778
                if (!dbuf.dptr)
 
779
                        continue;
 
780
 
 
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)
 
787
                        continue;
 
788
 
 
789
                *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
 
790
                if (!*list) {
 
791
                        DEBUG(0,("get_ntforms: Realloc fail.\n"));
 
792
                        return 0;
 
793
                }
 
794
                (*list)[n] = form;
 
795
                n++;
 
796
        }
 
797
 
 
798
 
 
799
        return n;
 
800
}
 
801
 
 
802
/****************************************************************************
 
803
write a form struct list
 
804
****************************************************************************/
 
805
 
 
806
int write_ntforms(nt_forms_struct **list, int number)
 
807
{
 
808
        TALLOC_CTX *ctx = talloc_tos();
 
809
        char *buf = NULL;
 
810
        char *key = NULL;
 
811
        int len;
 
812
        TDB_DATA dbuf;
 
813
        int i;
 
814
 
 
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,
 
820
                               (*list)[i].bottom);
 
821
                if (!len) {
 
822
                        continue;
 
823
                }
 
824
                buf = TALLOC_ARRAY(ctx, char, len);
 
825
                if (!buf) {
 
826
                        return 0;
 
827
                }
 
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,
 
831
                               (*list)[i].bottom);
 
832
                key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
 
833
                if (!key) {
 
834
                        return 0;
 
835
                }
 
836
                dbuf.dsize = len;
 
837
                dbuf.dptr = (uint8 *)buf;
 
838
                if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
 
839
                        TALLOC_FREE(key);
 
840
                        TALLOC_FREE(buf);
 
841
                        break;
 
842
                }
 
843
                TALLOC_FREE(key);
 
844
                TALLOC_FREE(buf);
 
845
       }
 
846
 
 
847
       return i;
 
848
}
 
849
 
 
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)
 
854
{
 
855
        int n=0;
 
856
        bool update;
 
857
 
 
858
        /*
 
859
         * NT tries to add forms even when
 
860
         * they are already in the base
 
861
         * only update the values if already present
 
862
         */
 
863
 
 
864
        update=False;
 
865
 
 
866
        for (n=0; n<*count; n++) {
 
867
                if ( strequal((*list)[n].name, form->form_name) ) {
 
868
                        update=True;
 
869
                        break;
 
870
                }
 
871
        }
 
872
 
 
873
        if (update==False) {
 
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"));
 
876
                        return False;
 
877
                }
 
878
                fstrcpy((*list)[n].name, form->form_name);
 
879
                (*count)++;
 
880
        }
 
881
 
 
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;
 
889
 
 
890
        DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
 
891
                update ? "updated" : "added", form->form_name));
 
892
 
 
893
        return True;
 
894
}
 
895
 
 
896
/****************************************************************************
 
897
 Delete a named form struct.
 
898
****************************************************************************/
 
899
 
 
900
bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
 
901
{
 
902
        char *key = NULL;
 
903
        int n=0;
 
904
 
 
905
        *ret = WERR_OK;
 
906
 
 
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));
 
910
                        break;
 
911
                }
 
912
        }
 
913
 
 
914
        if (n == *count) {
 
915
                DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
 
916
                *ret = WERR_INVALID_PARAM;
 
917
                return False;
 
918
        }
 
919
 
 
920
        if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
 
921
                *ret = WERR_NOMEM;
 
922
                return false;
 
923
        }
 
924
        if (tdb_delete_bystring(tdb_forms, key) != 0) {
 
925
                SAFE_FREE(key);
 
926
                *ret = WERR_NOMEM;
 
927
                return False;
 
928
        }
 
929
        SAFE_FREE(key);
 
930
        return true;
 
931
}
 
932
 
 
933
/****************************************************************************
 
934
 Update a form struct.
 
935
****************************************************************************/
 
936
 
 
937
void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
 
938
{
 
939
        int n=0;
 
940
 
 
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)))
 
945
                        break;
 
946
        }
 
947
 
 
948
        if (n==count) return;
 
949
 
 
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;
 
957
}
 
958
 
 
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)
 
964
{
 
965
        int total=0;
 
966
        const char *short_archi;
 
967
        char *key = NULL;
 
968
        TDB_DATA kbuf, newkey;
 
969
 
 
970
        short_archi = get_short_archi(architecture);
 
971
        if (!short_archi) {
 
972
                return 0;
 
973
        }
 
974
 
 
975
        if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
 
976
                                short_archi, version) < 0) {
 
977
                return 0;
 
978
        }
 
979
 
 
980
        for (kbuf = tdb_firstkey(tdb_drivers);
 
981
             kbuf.dptr;
 
982
             newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
 
983
 
 
984
                if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
 
985
                        continue;
 
986
 
 
987
                if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
 
988
                        DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
 
989
                        SAFE_FREE(key);
 
990
                        return -1;
 
991
                }
 
992
 
 
993
                fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
 
994
                total++;
 
995
        }
 
996
 
 
997
        SAFE_FREE(key);
 
998
        return(total);
 
999
}
 
1000
 
 
1001
/****************************************************************************
 
1002
 Function to do the mapping between the long architecture name and
 
1003
 the short one.
 
1004
****************************************************************************/
 
1005
 
 
1006
const char *get_short_archi(const char *long_archi)
 
1007
{
 
1008
        int i=-1;
 
1009
 
 
1010
        DEBUG(107,("Getting architecture dependant directory\n"));
 
1011
        do {
 
1012
                i++;
 
1013
        } while ( (archi_table[i].long_archi!=NULL ) &&
 
1014
                  StrCaseCmp(long_archi, archi_table[i].long_archi) );
 
1015
 
 
1016
        if (archi_table[i].long_archi==NULL) {
 
1017
                DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
 
1018
                return NULL;
 
1019
        }
 
1020
 
 
1021
        /* this might be client code - but shouldn't this be an fstrcpy etc? */
 
1022
 
 
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));
 
1026
 
 
1027
        return archi_table[i].short_archi;
 
1028
}
 
1029
 
 
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
****************************************************************************/
 
1037
 
 
1038
static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
 
1039
{
 
1040
        int     i;
 
1041
        char    *buf = NULL;
 
1042
        ssize_t byte_count;
 
1043
 
 
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));
 
1047
                goto error_exit;
 
1048
        }
 
1049
 
 
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;
 
1054
        }
 
1055
 
 
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;
 
1061
        }
 
1062
 
 
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",
 
1066
                                fname, errno));
 
1067
                /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
 
1068
                goto no_version_info;
 
1069
        }
 
1070
 
 
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;
 
1077
        }
 
1078
 
 
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;
 
1083
 
 
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",
 
1089
                                fname, errno));
 
1090
                        goto error_exit;
 
1091
                }
 
1092
 
 
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)
 
1097
                        goto error_exit;
 
1098
 
 
1099
                SAFE_FREE(buf);
 
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));
 
1103
                        goto error_exit;
 
1104
                }
 
1105
 
 
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));
 
1109
                        goto error_exit;
 
1110
                }
 
1111
 
 
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;
 
1115
 
 
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);
 
1119
 
 
1120
                                if (section_bytes == 0)
 
1121
                                        goto error_exit;
 
1122
 
 
1123
                                SAFE_FREE(buf);
 
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));
 
1127
                                        goto error_exit;
 
1128
                                }
 
1129
 
 
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",
 
1133
                                                        fname, errno));
 
1134
                                        goto error_exit;
 
1135
                                }
 
1136
 
 
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));
 
1140
                                        goto error_exit;
 
1141
                                }
 
1142
 
 
1143
                                if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
 
1144
                                        goto error_exit;
 
1145
 
 
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;
 
1151
 
 
1152
                                                if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
 
1153
                                                        *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
 
1154
                                                        *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
 
1155
 
 
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));
 
1160
                                                        SAFE_FREE(buf);
 
1161
                                                        return 1;
 
1162
                                                }
 
1163
                                        }
 
1164
                                }
 
1165
                        }
 
1166
                }
 
1167
 
 
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));
 
1170
                SAFE_FREE(buf);
 
1171
                return 0;
 
1172
 
 
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. */
 
1179
                        goto error_exit;
 
1180
                }
 
1181
 
 
1182
                /* Allocate a bit more space to speed up things */
 
1183
                SAFE_FREE(buf);
 
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));
 
1187
                        goto error_exit;
 
1188
                }
 
1189
 
 
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;
 
1196
 
 
1197
                        for(i=0; i<byte_count; i++) {
 
1198
                                /* Fast skip past data that can't possibly match */
 
1199
                                if (buf[i] != 'V') continue;
 
1200
 
 
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) {
 
1204
                                        int bc;
 
1205
 
 
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) {
 
1209
 
 
1210
                                                DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
 
1211
                                                                 fname, errno));
 
1212
                                                goto error_exit;
 
1213
                                        }
 
1214
 
 
1215
                                        byte_count = bc + (byte_count - i);
 
1216
                                        if (byte_count<VS_VERSION_INFO_SIZE) break;
 
1217
 
 
1218
                                        i = 0;
 
1219
                                }
 
1220
 
 
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;
 
1230
 
 
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));
 
1237
                                        SAFE_FREE(buf);
 
1238
                                        return 1;
 
1239
                                }
 
1240
                        }
 
1241
                }
 
1242
 
 
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));
 
1245
                SAFE_FREE(buf);
 
1246
                return 0;
 
1247
 
 
1248
        } else
 
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)));
 
1252
 
 
1253
        no_version_info:
 
1254
                SAFE_FREE(buf);
 
1255
                return 0;
 
1256
 
 
1257
        error_exit:
 
1258
                SAFE_FREE(buf);
 
1259
                return -1;
 
1260
}
 
1261
 
 
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
****************************************************************************/
 
1271
 
 
1272
static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
 
1273
{
 
1274
        bool use_version = true;
 
1275
        char *filepath = NULL;
 
1276
 
 
1277
        uint32 new_major;
 
1278
        uint32 new_minor;
 
1279
        time_t new_create_time;
 
1280
 
 
1281
        uint32 old_major;
 
1282
        uint32 old_minor;
 
1283
        time_t old_create_time;
 
1284
 
 
1285
        files_struct    *fsp = NULL;
 
1286
        SMB_STRUCT_STAT st;
 
1287
        SMB_STRUCT_STAT stat_buf;
 
1288
 
 
1289
        NTSTATUS status;
 
1290
 
 
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;
 
1295
 
 
1296
        /* Get file version info (if available) for previous file (if it exists) */
 
1297
        filepath = driver_unix_convert(conn,old_file,&stat_buf);
 
1298
        if (!filepath) {
 
1299
                goto error_exit;
 
1300
        }
 
1301
 
 
1302
        status = SMB_VFS_CREATE_FILE(
 
1303
                conn,                                   /* conn */
 
1304
                NULL,                                   /* req */
 
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 */
 
1315
                NULL,                                   /* sd */
 
1316
                NULL,                                   /* ea_list */
 
1317
                &fsp,                                   /* result */
 
1318
                NULL,                                   /* pinfo */
 
1319
                &stat_buf);                             /* psbuf */
 
1320
 
 
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",
 
1324
                                filepath, errno));
 
1325
                return 1;
 
1326
 
 
1327
        } else {
 
1328
                int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
 
1329
                if (ret == -1) {
 
1330
                        goto error_exit;
 
1331
                }
 
1332
 
 
1333
                if (!ret) {
 
1334
                        DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
 
1335
                                         old_file));
 
1336
                        use_version = false;
 
1337
                        if (SMB_VFS_FSTAT(fsp, &st) == -1) {
 
1338
                                 goto error_exit;
 
1339
                        }
 
1340
                        old_create_time = st.st_mtime;
 
1341
                        DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
 
1342
                                (long)old_create_time));
 
1343
                }
 
1344
        }
 
1345
        close_file(NULL, fsp, NORMAL_CLOSE);
 
1346
        fsp = NULL;
 
1347
 
 
1348
        /* Get file version info (if available) for new file */
 
1349
        filepath = driver_unix_convert(conn,new_file,&stat_buf);
 
1350
        if (!filepath) {
 
1351
                goto error_exit;
 
1352
        }
 
1353
 
 
1354
        status = SMB_VFS_CREATE_FILE(
 
1355
                conn,                                   /* conn */
 
1356
                NULL,                                   /* req */
 
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 */
 
1367
                NULL,                                   /* sd */
 
1368
                NULL,                                   /* ea_list */
 
1369
                &fsp,                                   /* result */
 
1370
                NULL,                                   /* pinfo */
 
1371
                &stat_buf);                             /* psbuf */
 
1372
 
 
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",
 
1376
                                filepath, errno));
 
1377
                goto error_exit;
 
1378
 
 
1379
        } else {
 
1380
                int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
 
1381
                if (ret == -1) {
 
1382
                        goto error_exit;
 
1383
                }
 
1384
 
 
1385
                if (!ret) {
 
1386
                        DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
 
1387
                                         new_file));
 
1388
                        use_version = false;
 
1389
                        if (SMB_VFS_FSTAT(fsp, &st) == -1) {
 
1390
                                goto error_exit;
 
1391
                        }
 
1392
                        new_create_time = st.st_mtime;
 
1393
                        DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
 
1394
                                (long)new_create_time));
 
1395
                }
 
1396
        }
 
1397
        close_file(NULL, fsp, NORMAL_CLOSE);
 
1398
        fsp = NULL;
 
1399
 
 
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)) {
 
1404
 
 
1405
                        DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
 
1406
                        return 1;
 
1407
                }
 
1408
                else {
 
1409
                        DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
 
1410
                        return 0;
 
1411
                }
 
1412
 
 
1413
        } else {
 
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));
 
1417
                        return 1;
 
1418
                }
 
1419
                else {
 
1420
                        DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
 
1421
                        return 0;
 
1422
                }
 
1423
        }
 
1424
 
 
1425
        error_exit:
 
1426
                if(fsp)
 
1427
                        close_file(NULL, fsp, NORMAL_CLOSE);
 
1428
                return -1;
 
1429
}
 
1430
 
 
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,
 
1437
                                   WERROR *perr)
 
1438
{
 
1439
        int               cversion;
 
1440
        NTSTATUS          nt_status;
 
1441
        char *driverpath = NULL;
 
1442
        files_struct      *fsp = NULL;
 
1443
        SMB_STRUCT_STAT   st;
 
1444
        connection_struct *conn = NULL;
 
1445
        NTSTATUS status;
 
1446
        char *oldcwd;
 
1447
        fstring printdollar;
 
1448
        int printdollar_snum;
 
1449
 
 
1450
        SET_STAT_INVALID(st);
 
1451
 
 
1452
        *perr = WERR_INVALID_PARAM;
 
1453
 
 
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"));
 
1457
                *perr = WERR_OK;
 
1458
                return 0;
 
1459
        }
 
1460
 
 
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"));
 
1464
                *perr = WERR_OK;
 
1465
                return 3;
 
1466
        }
 
1467
 
 
1468
        fstrcpy(printdollar, "print$");
 
1469
 
 
1470
        printdollar_snum = find_service(printdollar);
 
1471
        if (printdollar_snum == -1) {
 
1472
                *perr = WERR_NO_SUCH_SHARE;
 
1473
                return -1;
 
1474
        }
 
1475
 
 
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);
 
1483
                return -1;
 
1484
        }
 
1485
 
 
1486
        /* Open the driver file (Portable Executable format) and determine the
 
1487
         * deriver the cversion. */
 
1488
        driverpath = talloc_asprintf(talloc_tos(),
 
1489
                                        "%s/%s",
 
1490
                                        architecture,
 
1491
                                        driverpath_in);
 
1492
        if (!driverpath) {
 
1493
                *perr = WERR_NOMEM;
 
1494
                goto error_exit;
 
1495
        }
 
1496
 
 
1497
        driverpath = driver_unix_convert(conn,driverpath,&st);
 
1498
        if (!driverpath) {
 
1499
                *perr = WERR_NOMEM;
 
1500
                goto error_exit;
 
1501
        }
 
1502
 
 
1503
        if (!vfs_file_exist(conn, driverpath, &st)) {
 
1504
                *perr = WERR_BADFILE;
 
1505
                goto error_exit;
 
1506
        }
 
1507
 
 
1508
        status = SMB_VFS_CREATE_FILE(
 
1509
                conn,                                   /* conn */
 
1510
                NULL,                                   /* req */
 
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 */
 
1521
                NULL,                                   /* sd */
 
1522
                NULL,                                   /* ea_list */
 
1523
                &fsp,                                   /* result */
 
1524
                NULL,                                   /* pinfo */
 
1525
                &st);                                   /* psbuf */
 
1526
 
 
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;
 
1531
                goto error_exit;
 
1532
        } else {
 
1533
                uint32 major;
 
1534
                uint32 minor;
 
1535
                int    ret = get_file_version(fsp, driverpath, &major, &minor);
 
1536
                if (ret == -1) goto error_exit;
 
1537
 
 
1538
                if (!ret) {
 
1539
                        DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
 
1540
                        goto error_exit;
 
1541
                }
 
1542
 
 
1543
                /*
 
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.
 
1548
                 * JRR 010716
 
1549
                */
 
1550
                cversion = major & 0x0000ffff;
 
1551
                switch (cversion) {
 
1552
                        case 2: /* WinNT drivers */
 
1553
                        case 3: /* Win2K drivers */
 
1554
                                break;
 
1555
 
 
1556
                        default:
 
1557
                                DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n",
 
1558
                                        driverpath, cversion));
 
1559
                                goto error_exit;
 
1560
                }
 
1561
 
 
1562
                DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
 
1563
                                  driverpath, major, minor));
 
1564
        }
 
1565
 
 
1566
        DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
 
1567
                driverpath, cversion));
 
1568
 
 
1569
        goto done;
 
1570
 
 
1571
 error_exit:
 
1572
        cversion = -1;
 
1573
 done:
 
1574
        if (fsp != NULL) {
 
1575
                close_file(NULL, fsp, NORMAL_CLOSE);
 
1576
        }
 
1577
        if (conn != NULL) {
 
1578
                vfs_ChDir(conn, oldcwd);
 
1579
                conn_free_internal(conn);
 
1580
        }
 
1581
        if (cversion != -1) {
 
1582
                *perr = WERR_OK;
 
1583
        }
 
1584
        return cversion;
 
1585
}
 
1586
 
 
1587
/****************************************************************************
 
1588
****************************************************************************/
 
1589
static WERROR clean_up_driver_struct_level_3(struct pipes_struct *rpc_pipe,
 
1590
                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
 
1591
{
 
1592
        const char *architecture;
 
1593
        fstring new_name;
 
1594
        char *p;
 
1595
        int i;
 
1596
        WERROR err;
 
1597
 
 
1598
        /* clean up the driver name.
 
1599
         * we can get .\driver.dll
 
1600
         * or worse c:\windows\system\driver.dll !
 
1601
         */
 
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);
 
1606
        }
 
1607
 
 
1608
        if ((p = strrchr(driver->datafile,'\\')) != NULL) {
 
1609
                fstrcpy(new_name, p+1);
 
1610
                fstrcpy(driver->datafile, new_name);
 
1611
        }
 
1612
 
 
1613
        if ((p = strrchr(driver->configfile,'\\')) != NULL) {
 
1614
                fstrcpy(new_name, p+1);
 
1615
                fstrcpy(driver->configfile, new_name);
 
1616
        }
 
1617
 
 
1618
        if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
 
1619
                fstrcpy(new_name, p+1);
 
1620
                fstrcpy(driver->helpfile, new_name);
 
1621
        }
 
1622
 
 
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);
 
1628
                        }
 
1629
                }
 
1630
        }
 
1631
 
 
1632
        architecture = get_short_archi(driver->environment);
 
1633
        if (!architecture) {
 
1634
                return WERR_UNKNOWN_PRINTER_DRIVER;
 
1635
        }
 
1636
 
 
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.
 
1640
         *
 
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
 
1645
         *      NT 4: cversion=2
 
1646
         *      NT2K: cversion=3
 
1647
         */
 
1648
        if ((driver->cversion = get_correct_cversion(rpc_pipe, architecture,
 
1649
                                                     driver->driverpath,
 
1650
                                                     &err)) == -1)
 
1651
                return err;
 
1652
 
 
1653
        return WERR_OK;
 
1654
}
 
1655
 
 
1656
/****************************************************************************
 
1657
****************************************************************************/
 
1658
static WERROR clean_up_driver_struct_level_6(struct pipes_struct *rpc_pipe,
 
1659
                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
 
1660
{
 
1661
        const char *architecture;
 
1662
        fstring new_name;
 
1663
        char *p;
 
1664
        int i;
 
1665
        WERROR err;
 
1666
 
 
1667
        /* clean up the driver name.
 
1668
         * we can get .\driver.dll
 
1669
         * or worse c:\windows\system\driver.dll !
 
1670
         */
 
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);
 
1675
        }
 
1676
 
 
1677
        if ((p = strrchr(driver->datafile,'\\')) != NULL) {
 
1678
                fstrcpy(new_name, p+1);
 
1679
                fstrcpy(driver->datafile, new_name);
 
1680
        }
 
1681
 
 
1682
        if ((p = strrchr(driver->configfile,'\\')) != NULL) {
 
1683
                fstrcpy(new_name, p+1);
 
1684
                fstrcpy(driver->configfile, new_name);
 
1685
        }
 
1686
 
 
1687
        if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
 
1688
                fstrcpy(new_name, p+1);
 
1689
                fstrcpy(driver->helpfile, new_name);
 
1690
        }
 
1691
 
 
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);
 
1697
                        }
 
1698
                }
 
1699
        }
 
1700
 
 
1701
        architecture = get_short_archi(driver->environment);
 
1702
        if (!architecture) {
 
1703
                return WERR_UNKNOWN_PRINTER_DRIVER;
 
1704
        }
 
1705
 
 
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.
 
1709
         *
 
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
 
1714
         *      NT 4: cversion=2
 
1715
         *      NT2K: cversion=3
 
1716
         */
 
1717
 
 
1718
        if ((driver->version = get_correct_cversion(rpc_pipe, architecture,
 
1719
                                                    driver->driverpath,
 
1720
                                                    &err)) == -1)
 
1721
                        return err;
 
1722
 
 
1723
        return WERR_OK;
 
1724
}
 
1725
 
 
1726
/****************************************************************************
 
1727
****************************************************************************/
 
1728
WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
 
1729
                              NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
 
1730
                              uint32 level)
 
1731
{
 
1732
        switch (level) {
 
1733
                case 3:
 
1734
                {
 
1735
                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
 
1736
                        driver=driver_abstract.info_3;
 
1737
                        return clean_up_driver_struct_level_3(rpc_pipe,
 
1738
                                                              driver);
 
1739
                }
 
1740
                case 6:
 
1741
                {
 
1742
                        NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
 
1743
                        driver=driver_abstract.info_6;
 
1744
                        return clean_up_driver_struct_level_6(rpc_pipe,
 
1745
                                                              driver);
 
1746
                }
 
1747
                default:
 
1748
                        return WERR_INVALID_PARAM;
 
1749
        }
 
1750
}
 
1751
 
 
1752
/****************************************************************************
 
1753
 This function sucks and should be replaced. JRA.
 
1754
****************************************************************************/
 
1755
 
 
1756
static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
 
1757
{
 
1758
    dst->cversion  = src->version;
 
1759
 
 
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;
 
1769
}
 
1770
 
 
1771
#if 0 /* Debugging function */
 
1772
 
 
1773
static char* ffmt(unsigned char *c){
 
1774
        int i;
 
1775
        static char ffmt_str[17];
 
1776
 
 
1777
        for (i=0; i<16; i++) {
 
1778
                if ((c[i] < ' ') || (c[i] > '~'))
 
1779
                        ffmt_str[i]='.';
 
1780
                else
 
1781
                        ffmt_str[i]=c[i];
 
1782
        }
 
1783
    ffmt_str[16]='\0';
 
1784
        return ffmt_str;
 
1785
}
 
1786
 
 
1787
#endif
 
1788
 
 
1789
/****************************************************************************
 
1790
****************************************************************************/
 
1791
 
 
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,
 
1797
                                                uint32_t version)
 
1798
{
 
1799
        char *old_name = NULL;
 
1800
        char *new_name = NULL;
 
1801
        SMB_STRUCT_STAT st;
 
1802
        NTSTATUS status;
 
1803
 
 
1804
        old_name = talloc_asprintf(mem_ctx, "%s/%s",
 
1805
                                   short_architecture, driver_file);
 
1806
        W_ERROR_HAVE_NO_MEMORY(old_name);
 
1807
 
 
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);
 
1811
 
 
1812
        if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
 
1813
 
 
1814
                old_name = driver_unix_convert(conn, old_name, &st);
 
1815
                W_ERROR_HAVE_NO_MEMORY(old_name);
 
1816
 
 
1817
                DEBUG(10,("move_driver_file_to_download_area: copying '%s' to '%s'\n",
 
1818
                        old_name, new_name));
 
1819
 
 
1820
                status = copy_file(mem_ctx, conn, old_name, new_name,
 
1821
                                   OPENX_FILE_EXISTS_TRUNCATE |
 
1822
                                   OPENX_FILE_CREATE_IF_NOT_EXIST,
 
1823
                                   0, false);
 
1824
 
 
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;
 
1829
                }
 
1830
        }
 
1831
 
 
1832
        return WERR_OK;
 
1833
}
 
1834
 
 
1835
WERROR move_driver_to_download_area(struct pipes_struct *p,
 
1836
                                    NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
 
1837
                                    uint32 level, WERROR *perr)
 
1838
{
 
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;
 
1844
        NTSTATUS nt_status;
 
1845
        SMB_STRUCT_STAT st;
 
1846
        int i;
 
1847
        TALLOC_CTX *ctx = talloc_tos();
 
1848
        int ver = 0;
 
1849
        char *oldcwd;
 
1850
        fstring printdollar;
 
1851
        int printdollar_snum;
 
1852
 
 
1853
        *perr = WERR_OK;
 
1854
 
 
1855
        switch (level) {
 
1856
        case 3:
 
1857
                driver = driver_abstract.info_3;
 
1858
                break;
 
1859
        case 6:
 
1860
                convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
 
1861
                driver = &converted_driver;
 
1862
                break;
 
1863
        default:
 
1864
                DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
 
1865
                return WERR_UNKNOWN_LEVEL;
 
1866
        }
 
1867
 
 
1868
        short_architecture = get_short_archi(driver->environment);
 
1869
        if (!short_architecture) {
 
1870
                return WERR_UNKNOWN_PRINTER_DRIVER;
 
1871
        }
 
1872
 
 
1873
        fstrcpy(printdollar, "print$");
 
1874
 
 
1875
        printdollar_snum = find_service(printdollar);
 
1876
        if (printdollar_snum == -1) {
 
1877
                *perr = WERR_NO_SUCH_SHARE;
 
1878
                return WERR_NO_SUCH_SHARE;
 
1879
        }
 
1880
 
 
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);
 
1888
                return *perr;
 
1889
        }
 
1890
 
 
1891
        new_dir = talloc_asprintf(ctx,
 
1892
                                "%s/%d",
 
1893
                                short_architecture,
 
1894
                                driver->cversion);
 
1895
        if (!new_dir) {
 
1896
                *perr = WERR_NOMEM;
 
1897
                goto err_exit;
 
1898
        }
 
1899
        new_dir = driver_unix_convert(conn,new_dir,&st);
 
1900
        if (!new_dir) {
 
1901
                *perr = WERR_NOMEM;
 
1902
                goto err_exit;
 
1903
        }
 
1904
 
 
1905
        DEBUG(5,("Creating first directory: %s\n", new_dir));
 
1906
 
 
1907
        create_directory(conn, NULL, new_dir);
 
1908
 
 
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.
 
1916
         *
 
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
 
1924
         */
 
1925
 
 
1926
        DEBUG(5,("Moving files now !\n"));
 
1927
 
 
1928
        if (driver->driverpath && strlen(driver->driverpath)) {
 
1929
 
 
1930
                *perr = move_driver_file_to_download_area(ctx,
 
1931
                                                          conn,
 
1932
                                                          driver->driverpath,
 
1933
                                                          short_architecture,
 
1934
                                                          driver->cversion,
 
1935
                                                          ver);
 
1936
                if (!W_ERROR_IS_OK(*perr)) {
 
1937
                        if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
 
1938
                                ver = -1;
 
1939
                        }
 
1940
                        goto err_exit;
 
1941
                }
 
1942
        }
 
1943
 
 
1944
        if (driver->datafile && strlen(driver->datafile)) {
 
1945
                if (!strequal(driver->datafile, driver->driverpath)) {
 
1946
 
 
1947
                        *perr = move_driver_file_to_download_area(ctx,
 
1948
                                                                  conn,
 
1949
                                                                  driver->datafile,
 
1950
                                                                  short_architecture,
 
1951
                                                                  driver->cversion,
 
1952
                                                                  ver);
 
1953
                        if (!W_ERROR_IS_OK(*perr)) {
 
1954
                                if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
 
1955
                                        ver = -1;
 
1956
                                }
 
1957
                                goto err_exit;
 
1958
                        }
 
1959
                }
 
1960
        }
 
1961
 
 
1962
        if (driver->configfile && strlen(driver->configfile)) {
 
1963
                if (!strequal(driver->configfile, driver->driverpath) &&
 
1964
                    !strequal(driver->configfile, driver->datafile)) {
 
1965
 
 
1966
                        *perr = move_driver_file_to_download_area(ctx,
 
1967
                                                                  conn,
 
1968
                                                                  driver->configfile,
 
1969
                                                                  short_architecture,
 
1970
                                                                  driver->cversion,
 
1971
                                                                  ver);
 
1972
                        if (!W_ERROR_IS_OK(*perr)) {
 
1973
                                if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
 
1974
                                        ver = -1;
 
1975
                                }
 
1976
                                goto err_exit;
 
1977
                        }
 
1978
                }
 
1979
        }
 
1980
 
 
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)) {
 
1985
 
 
1986
                        *perr = move_driver_file_to_download_area(ctx,
 
1987
                                                                  conn,
 
1988
                                                                  driver->helpfile,
 
1989
                                                                  short_architecture,
 
1990
                                                                  driver->cversion,
 
1991
                                                                  ver);
 
1992
                        if (!W_ERROR_IS_OK(*perr)) {
 
1993
                                if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
 
1994
                                        ver = -1;
 
1995
                                }
 
1996
                                goto err_exit;
 
1997
                        }
 
1998
                }
 
1999
        }
 
2000
 
 
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)) {
 
2007
                                int j;
 
2008
                                for (j=0; j < i; j++) {
 
2009
                                        if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
 
2010
                                                goto NextDriver;
 
2011
                                        }
 
2012
                                }
 
2013
 
 
2014
                                *perr = move_driver_file_to_download_area(ctx,
 
2015
                                                                          conn,
 
2016
                                                                          driver->dependentfiles[i],
 
2017
                                                                          short_architecture,
 
2018
                                                                          driver->cversion,
 
2019
                                                                          ver);
 
2020
                                if (!W_ERROR_IS_OK(*perr)) {
 
2021
                                        if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
 
2022
                                                ver = -1;
 
2023
                                        }
 
2024
                                        goto err_exit;
 
2025
                                }
 
2026
                        }
 
2027
                NextDriver: ;
 
2028
                }
 
2029
        }
 
2030
 
 
2031
  err_exit:
 
2032
 
 
2033
        if (conn != NULL) {
 
2034
                vfs_ChDir(conn, oldcwd);
 
2035
                conn_free_internal(conn);
 
2036
        }
 
2037
 
 
2038
        if (W_ERROR_EQUAL(*perr, WERR_OK)) {
 
2039
                return WERR_OK;
 
2040
        }
 
2041
        if (ver == -1) {
 
2042
                return WERR_UNKNOWN_PRINTER_DRIVER;
 
2043
        }
 
2044
        return (*perr);
 
2045
}
 
2046
 
 
2047
/****************************************************************************
 
2048
****************************************************************************/
 
2049
 
 
2050
static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
 
2051
{
 
2052
        TALLOC_CTX *ctx = talloc_tos();
 
2053
        int len, buflen;
 
2054
        const char *architecture;
 
2055
        char *directory = NULL;
 
2056
        fstring temp_name;
 
2057
        char *key = NULL;
 
2058
        uint8 *buf;
 
2059
        int i, ret;
 
2060
        TDB_DATA dbuf;
 
2061
 
 
2062
        architecture = get_short_archi(driver->environment);
 
2063
        if (!architecture) {
 
2064
                return (uint32)-1;
 
2065
        }
 
2066
 
 
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.
 
2070
         */
 
2071
 
 
2072
        directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
 
2073
                        architecture, driver->cversion);
 
2074
        if (!directory) {
 
2075
                return (uint32)-1;
 
2076
        }
 
2077
 
 
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."
 
2083
         */
 
2084
        if (strlen(driver->driverpath)) {
 
2085
                fstrcpy(temp_name, driver->driverpath);
 
2086
                slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
 
2087
        }
 
2088
 
 
2089
        if (strlen(driver->datafile)) {
 
2090
                fstrcpy(temp_name, driver->datafile);
 
2091
                slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
 
2092
        }
 
2093
 
 
2094
        if (strlen(driver->configfile)) {
 
2095
                fstrcpy(temp_name, driver->configfile);
 
2096
                slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
 
2097
        }
 
2098
 
 
2099
        if (strlen(driver->helpfile)) {
 
2100
                fstrcpy(temp_name, driver->helpfile);
 
2101
                slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
 
2102
        }
 
2103
 
 
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);
 
2108
                }
 
2109
        }
 
2110
 
 
2111
        key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
 
2112
                        architecture, driver->cversion, driver->name);
 
2113
        if (!key) {
 
2114
                return (uint32)-1;
 
2115
        }
 
2116
 
 
2117
        DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
 
2118
 
 
2119
        buf = NULL;
 
2120
        len = buflen = 0;
 
2121
 
 
2122
 again:
 
2123
        len = 0;
 
2124
        len += tdb_pack(buf+len, buflen-len, "dffffffff",
 
2125
                        driver->cversion,
 
2126
                        driver->name,
 
2127
                        driver->environment,
 
2128
                        driver->driverpath,
 
2129
                        driver->datafile,
 
2130
                        driver->configfile,
 
2131
                        driver->helpfile,
 
2132
                        driver->monitorname,
 
2133
                        driver->defaultdatatype);
 
2134
 
 
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]);
 
2139
                }
 
2140
        }
 
2141
 
 
2142
        if (len != buflen) {
 
2143
                buf = (uint8 *)SMB_REALLOC(buf, len);
 
2144
                if (!buf) {
 
2145
                        DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
 
2146
                        ret = -1;
 
2147
                        goto done;
 
2148
                }
 
2149
                buflen = len;
 
2150
                goto again;
 
2151
        }
 
2152
 
 
2153
        dbuf.dptr = buf;
 
2154
        dbuf.dsize = len;
 
2155
 
 
2156
        ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
 
2157
 
 
2158
done:
 
2159
        if (ret)
 
2160
                DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
 
2161
 
 
2162
        SAFE_FREE(buf);
 
2163
        return ret;
 
2164
}
 
2165
 
 
2166
/****************************************************************************
 
2167
****************************************************************************/
 
2168
static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
 
2169
{
 
2170
        NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
 
2171
 
 
2172
        ZERO_STRUCT(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;
 
2183
 
 
2184
        return add_a_printer_driver_3(&info3);
 
2185
}
 
2186
 
 
2187
 
 
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)
 
2191
{
 
2192
        NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
 
2193
 
 
2194
        ZERO_STRUCT(info);
 
2195
 
 
2196
        fstrcpy(info.name, driver);
 
2197
        fstrcpy(info.defaultdatatype, "RAW");
 
2198
 
 
2199
        fstrcpy(info.driverpath, "");
 
2200
        fstrcpy(info.datafile, "");
 
2201
        fstrcpy(info.configfile, "");
 
2202
        fstrcpy(info.helpfile, "");
 
2203
 
 
2204
        if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
 
2205
                return WERR_NOMEM;
 
2206
 
 
2207
        memset(info.dependentfiles, '\0', 2*sizeof(fstring));
 
2208
        fstrcpy(info.dependentfiles[0], "");
 
2209
 
 
2210
        *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
 
2211
        if (!*info_ptr) {
 
2212
                SAFE_FREE(info.dependentfiles);
 
2213
                return WERR_NOMEM;
 
2214
        }
 
2215
 
 
2216
        return WERR_OK;
 
2217
}
 
2218
 
 
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,
 
2223
                                     uint32_t version)
 
2224
{
 
2225
        NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
 
2226
        TDB_DATA dbuf;
 
2227
        const char *architecture;
 
2228
        int len = 0;
 
2229
        int i;
 
2230
        char *key = NULL;
 
2231
 
 
2232
        ZERO_STRUCT(driver);
 
2233
 
 
2234
        architecture = get_short_archi(arch);
 
2235
        if ( !architecture ) {
 
2236
                return WERR_UNKNOWN_PRINTER_DRIVER;
 
2237
        }
 
2238
 
 
2239
        /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
 
2240
 
 
2241
        if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
 
2242
                version = 0;
 
2243
 
 
2244
        DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
 
2245
 
 
2246
        if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
 
2247
                                architecture, version, drivername) < 0) {
 
2248
                return WERR_NOMEM;
 
2249
        }
 
2250
 
 
2251
        dbuf = tdb_fetch_bystring(tdb_drivers, key);
 
2252
        if (!dbuf.dptr) {
 
2253
                SAFE_FREE(key);
 
2254
                return WERR_UNKNOWN_PRINTER_DRIVER;
 
2255
        }
 
2256
 
 
2257
        len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
 
2258
                          &driver.cversion,
 
2259
                          driver.name,
 
2260
                          driver.environment,
 
2261
                          driver.driverpath,
 
2262
                          driver.datafile,
 
2263
                          driver.configfile,
 
2264
                          driver.helpfile,
 
2265
                          driver.monitorname,
 
2266
                          driver.defaultdatatype);
 
2267
 
 
2268
        i=0;
 
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"));
 
2273
                        break;
 
2274
                }
 
2275
 
 
2276
                len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
 
2277
                                  &driver.dependentfiles[i]);
 
2278
                i++;
 
2279
        }
 
2280
 
 
2281
        if ( driver.dependentfiles )
 
2282
                fstrcpy( driver.dependentfiles[i], "" );
 
2283
 
 
2284
        SAFE_FREE(dbuf.dptr);
 
2285
        SAFE_FREE(key);
 
2286
 
 
2287
        if (len != dbuf.dsize) {
 
2288
                SAFE_FREE(driver.dependentfiles);
 
2289
 
 
2290
                return get_a_printer_driver_3_default(info_ptr, drivername, arch);
 
2291
        }
 
2292
 
 
2293
        *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
 
2294
        if (!*info_ptr) {
 
2295
                SAFE_FREE(driver.dependentfiles);
 
2296
                return WERR_NOMEM;
 
2297
        }
 
2298
 
 
2299
        return WERR_OK;
 
2300
}
 
2301
 
 
2302
/****************************************************************************
 
2303
 Debugging function, dump at level 6 the struct in the logs.
 
2304
****************************************************************************/
 
2305
 
 
2306
static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
 
2307
{
 
2308
        uint32 result;
 
2309
        NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
 
2310
        int i;
 
2311
 
 
2312
        DEBUG(20,("Dumping printer driver at level [%d]\n", level));
 
2313
 
 
2314
        switch (level)
 
2315
        {
 
2316
                case 3:
 
2317
                {
 
2318
                        if (driver.info_3 == NULL)
 
2319
                                result=5;
 
2320
                        else {
 
2321
                                info3=driver.info_3;
 
2322
 
 
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));
 
2332
 
 
2333
                                for (i=0; info3->dependentfiles &&
 
2334
                                          *info3->dependentfiles[i]; i++) {
 
2335
                                        DEBUGADD(20,("dependentfile:[%s]\n",
 
2336
                                                      info3->dependentfiles[i]));
 
2337
                                }
 
2338
                                result=0;
 
2339
                        }
 
2340
                        break;
 
2341
                }
 
2342
                default:
 
2343
                        DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
 
2344
                        result=1;
 
2345
                        break;
 
2346
        }
 
2347
 
 
2348
        return result;
 
2349
}
 
2350
 
 
2351
/****************************************************************************
 
2352
****************************************************************************/
 
2353
int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
 
2354
{
 
2355
        int len = 0;
 
2356
 
 
2357
        len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
 
2358
 
 
2359
        if (!nt_devmode)
 
2360
                return len;
 
2361
 
 
2362
        len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
 
2363
                        nt_devmode->devicename,
 
2364
                        nt_devmode->formname,
 
2365
 
 
2366
                        nt_devmode->specversion,
 
2367
                        nt_devmode->driverversion,
 
2368
                        nt_devmode->size,
 
2369
                        nt_devmode->driverextra,
 
2370
                        nt_devmode->orientation,
 
2371
                        nt_devmode->papersize,
 
2372
                        nt_devmode->paperlength,
 
2373
                        nt_devmode->paperwidth,
 
2374
                        nt_devmode->scale,
 
2375
                        nt_devmode->copies,
 
2376
                        nt_devmode->defaultsource,
 
2377
                        nt_devmode->printquality,
 
2378
                        nt_devmode->color,
 
2379
                        nt_devmode->duplex,
 
2380
                        nt_devmode->yresolution,
 
2381
                        nt_devmode->ttoption,
 
2382
                        nt_devmode->collate,
 
2383
                        nt_devmode->logpixels,
 
2384
 
 
2385
                        nt_devmode->fields,
 
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);
 
2400
 
 
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);
 
2405
        }
 
2406
 
 
2407
        DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
 
2408
 
 
2409
        return len;
 
2410
}
 
2411
 
 
2412
/****************************************************************************
 
2413
 Pack all values in all printer keys
 
2414
 ***************************************************************************/
 
2415
 
 
2416
static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
 
2417
{
 
2418
        int             len = 0;
 
2419
        int             i, j;
 
2420
        REGISTRY_VALUE  *val;
 
2421
        REGVAL_CTR      *val_ctr;
 
2422
        char *path = NULL;
 
2423
        int             num_values;
 
2424
 
 
2425
        if ( !data )
 
2426
                return 0;
 
2427
 
 
2428
        /* loop over all keys */
 
2429
 
 
2430
        for ( i=0; i<data->num_keys; i++ ) {
 
2431
                val_ctr = data->keys[i].values;
 
2432
                num_values = regval_ctr_numvals( val_ctr );
 
2433
 
 
2434
                /* pack the keyname followed by a empty value */
 
2435
 
 
2436
                len += tdb_pack(buf+len, buflen-len, "pPdB",
 
2437
                                &data->keys[i].name,
 
2438
                                data->keys[i].name,
 
2439
                                REG_NONE,
 
2440
                                0,
 
2441
                                NULL);
 
2442
 
 
2443
                /* now loop over all values */
 
2444
 
 
2445
                for ( j=0; j<num_values; j++ ) {
 
2446
                        /* pathname should be stored as <key>\<value> */
 
2447
 
 
2448
                        val = regval_ctr_specific_value( val_ctr, j );
 
2449
                        if (asprintf(&path, "%s\\%s",
 
2450
                                        data->keys[i].name,
 
2451
                                        regval_name(val)) < 0) {
 
2452
                                return -1;
 
2453
                        }
 
2454
 
 
2455
                        len += tdb_pack(buf+len, buflen-len, "pPdB",
 
2456
                                        val,
 
2457
                                        path,
 
2458
                                        regval_type(val),
 
2459
                                        regval_size(val),
 
2460
                                        regval_data_p(val) );
 
2461
 
 
2462
                        DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
 
2463
                        SAFE_FREE(path);
 
2464
                }
 
2465
 
 
2466
        }
 
2467
 
 
2468
        /* terminator */
 
2469
 
 
2470
        len += tdb_pack(buf+len, buflen-len, "p", NULL);
 
2471
 
 
2472
        return len;
 
2473
}
 
2474
 
 
2475
 
 
2476
/****************************************************************************
 
2477
 Delete a printer - this just deletes the printer info file, any open
 
2478
 handles are not affected.
 
2479
****************************************************************************/
 
2480
 
 
2481
uint32 del_a_printer(const char *sharename)
 
2482
{
 
2483
        TDB_DATA kbuf;
 
2484
        char *printdb_path = NULL;
 
2485
        TALLOC_CTX *ctx = talloc_tos();
 
2486
 
 
2487
        kbuf = make_printer_tdbkey(ctx, sharename);
 
2488
        tdb_delete(tdb_printers, kbuf);
 
2489
 
 
2490
        kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
 
2491
        tdb_delete(tdb_printers, kbuf);
 
2492
 
 
2493
        close_all_print_db();
 
2494
 
 
2495
        if (geteuid() == 0) {
 
2496
                if (asprintf(&printdb_path, "%s%s.tdb",
 
2497
                                cache_path("printing/"),
 
2498
                                sharename) < 0) {
 
2499
                        return (uint32)-1;
 
2500
                }
 
2501
                unlink(printdb_path);
 
2502
                SAFE_FREE(printdb_path);
 
2503
        }
 
2504
 
 
2505
        return 0;
 
2506
}
 
2507
 
 
2508
/****************************************************************************
 
2509
****************************************************************************/
 
2510
static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
 
2511
{
 
2512
        uint8 *buf;
 
2513
        int buflen, len;
 
2514
        int retlen;
 
2515
        WERROR ret;
 
2516
        TDB_DATA kbuf, dbuf;
 
2517
 
 
2518
        /*
 
2519
         * in addprinter: no servername and the printer is the name
 
2520
         * in setprinter: servername is \\server
 
2521
         *                and printer is \\server\\printer
 
2522
         *
 
2523
         * Samba manages only local printers.
 
2524
         * we currently don't support things like i
 
2525
         * path=\\other_server\printer
 
2526
         *
 
2527
         * We only store the printername, not \\server\printername
 
2528
         */
 
2529
 
 
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';
 
2534
        }
 
2535
 
 
2536
        /*
 
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.
 
2544
         */
 
2545
 
 
2546
        buf = NULL;
 
2547
        buflen = 0;
 
2548
 
 
2549
 again:
 
2550
        len = 0;
 
2551
        len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
 
2552
                        info->attributes,
 
2553
                        info->priority,
 
2554
                        info->default_priority,
 
2555
                        info->starttime,
 
2556
                        info->untiltime,
 
2557
                        info->status,
 
2558
                        info->cjobs,
 
2559
                        info->averageppm,
 
2560
                        info->changeid,
 
2561
                        info->c_setprinter,
 
2562
                        info->setuptime,
 
2563
                        info->servername,
 
2564
                        info->printername,
 
2565
                        info->sharename,
 
2566
                        info->portname,
 
2567
                        info->drivername,
 
2568
                        info->comment,
 
2569
                        info->location,
 
2570
                        info->sepfile,
 
2571
                        info->printprocessor,
 
2572
                        info->datatype,
 
2573
                        info->parameters);
 
2574
 
 
2575
        len += pack_devicemode(info->devmode, buf+len, buflen-len);
 
2576
        retlen = pack_values( info->data, buf+len, buflen-len );
 
2577
        if (retlen == -1) {
 
2578
                ret = WERR_NOMEM;
 
2579
                goto done;
 
2580
        }
 
2581
        len += retlen;
 
2582
 
 
2583
        if (buflen != len) {
 
2584
                buf = (uint8 *)SMB_REALLOC(buf, len);
 
2585
                if (!buf) {
 
2586
                        DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
 
2587
                        ret = WERR_NOMEM;
 
2588
                        goto done;
 
2589
                }
 
2590
                buflen = len;
 
2591
                goto again;
 
2592
        }
 
2593
 
 
2594
        kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
 
2595
 
 
2596
        dbuf.dptr = buf;
 
2597
        dbuf.dsize = len;
 
2598
 
 
2599
        ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
 
2600
 
 
2601
done:
 
2602
        if (!W_ERROR_IS_OK(ret))
 
2603
                DEBUG(8, ("error updating printer to tdb on disk\n"));
 
2604
 
 
2605
        SAFE_FREE(buf);
 
2606
 
 
2607
        DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
 
2608
                 info->sharename, info->drivername, info->portname, len));
 
2609
 
 
2610
        return ret;
 
2611
}
 
2612
 
 
2613
 
 
2614
/****************************************************************************
 
2615
 Malloc and return an NT devicemode.
 
2616
****************************************************************************/
 
2617
 
 
2618
NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
 
2619
{
 
2620
 
 
2621
        char adevice[MAXDEVICENAME];
 
2622
        NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
 
2623
 
 
2624
        if (nt_devmode == NULL) {
 
2625
                DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
 
2626
                return NULL;
 
2627
        }
 
2628
 
 
2629
        ZERO_STRUCTP(nt_devmode);
 
2630
 
 
2631
        slprintf(adevice, sizeof(adevice), "%s", default_devicename);
 
2632
        fstrcpy(nt_devmode->devicename, adevice);
 
2633
 
 
2634
        fstrcpy(nt_devmode->formname, "Letter");
 
2635
 
 
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;
 
2660
 
 
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;
 
2672
 
 
2673
        nt_devmode->nt_dev_private = NULL;
 
2674
        return nt_devmode;
 
2675
}
 
2676
 
 
2677
/****************************************************************************
 
2678
 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
 
2679
****************************************************************************/
 
2680
 
 
2681
void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
 
2682
{
 
2683
        NT_DEVICEMODE *nt_devmode = *devmode_ptr;
 
2684
 
 
2685
        if(nt_devmode == NULL)
 
2686
                return;
 
2687
 
 
2688
        DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
 
2689
 
 
2690
        SAFE_FREE(nt_devmode->nt_dev_private);
 
2691
        SAFE_FREE(*devmode_ptr);
 
2692
}
 
2693
 
 
2694
/****************************************************************************
 
2695
 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
 
2696
****************************************************************************/
 
2697
 
 
2698
static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
 
2699
{
 
2700
        NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
 
2701
 
 
2702
        if ( !info )
 
2703
                return;
 
2704
 
 
2705
        free_nt_devicemode(&info->devmode);
 
2706
 
 
2707
        TALLOC_FREE( *info_ptr );
 
2708
}
 
2709
 
 
2710
 
 
2711
/****************************************************************************
 
2712
****************************************************************************/
 
2713
int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
 
2714
{
 
2715
        int len = 0;
 
2716
        int extra_len = 0;
 
2717
        NT_DEVICEMODE devmode;
 
2718
 
 
2719
        ZERO_STRUCT(devmode);
 
2720
 
 
2721
        len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
 
2722
 
 
2723
        if (!*nt_devmode) return len;
 
2724
 
 
2725
        len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
 
2726
                          devmode.devicename,
 
2727
                          devmode.formname,
 
2728
 
 
2729
                          &devmode.specversion,
 
2730
                          &devmode.driverversion,
 
2731
                          &devmode.size,
 
2732
                          &devmode.driverextra,
 
2733
                          &devmode.orientation,
 
2734
                          &devmode.papersize,
 
2735
                          &devmode.paperlength,
 
2736
                          &devmode.paperwidth,
 
2737
                          &devmode.scale,
 
2738
                          &devmode.copies,
 
2739
                          &devmode.defaultsource,
 
2740
                          &devmode.printquality,
 
2741
                          &devmode.color,
 
2742
                          &devmode.duplex,
 
2743
                          &devmode.yresolution,
 
2744
                          &devmode.ttoption,
 
2745
                          &devmode.collate,
 
2746
                          &devmode.logpixels,
 
2747
 
 
2748
                          &devmode.fields,
 
2749
                          &devmode.bitsperpel,
 
2750
                          &devmode.pelswidth,
 
2751
                          &devmode.pelsheight,
 
2752
                          &devmode.displayflags,
 
2753
                          &devmode.displayfrequency,
 
2754
                          &devmode.icmmethod,
 
2755
                          &devmode.icmintent,
 
2756
                          &devmode.mediatype,
 
2757
                          &devmode.dithertype,
 
2758
                          &devmode.reserved1,
 
2759
                          &devmode.reserved2,
 
2760
                          &devmode.panningwidth,
 
2761
                          &devmode.panningheight,
 
2762
                          &devmode.nt_dev_private);
 
2763
 
 
2764
        if (devmode.nt_dev_private) {
 
2765
                /* the len in tdb_unpack is an int value and
 
2766
                 * devmode.driverextra is only a short
 
2767
                 */
 
2768
                len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
 
2769
                devmode.driverextra=(uint16)extra_len;
 
2770
 
 
2771
                /* check to catch an invalid TDB entry so we don't segfault */
 
2772
                if (devmode.driverextra == 0) {
 
2773
                        devmode.nt_dev_private = NULL;
 
2774
                }
 
2775
        }
 
2776
 
 
2777
        *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
 
2778
        if (!*nt_devmode) {
 
2779
                SAFE_FREE(devmode.nt_dev_private);
 
2780
                return -1;
 
2781
        }
 
2782
 
 
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));
 
2786
 
 
2787
        return len;
 
2788
}
 
2789
 
 
2790
/****************************************************************************
 
2791
 Allocate and initialize a new slot.
 
2792
***************************************************************************/
 
2793
 
 
2794
int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
 
2795
{
 
2796
        NT_PRINTER_KEY  *d;
 
2797
        int             key_index;
 
2798
 
 
2799
        if ( !name || !data )
 
2800
                return -1;
 
2801
 
 
2802
        /* allocate another slot in the NT_PRINTER_KEY array */
 
2803
 
 
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"));
 
2806
                return -1;
 
2807
        }
 
2808
 
 
2809
        data->keys = d;
 
2810
 
 
2811
        key_index = data->num_keys;
 
2812
 
 
2813
        /* initialze new key */
 
2814
 
 
2815
        data->keys[key_index].name = talloc_strdup( data, name );
 
2816
 
 
2817
        if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
 
2818
                return -1;
 
2819
 
 
2820
        data->num_keys++;
 
2821
 
 
2822
        DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
 
2823
 
 
2824
        return key_index;
 
2825
}
 
2826
 
 
2827
/****************************************************************************
 
2828
 search for a registry key name in the existing printer data
 
2829
 ***************************************************************************/
 
2830
 
 
2831
int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
 
2832
{
 
2833
        int i;
 
2834
 
 
2835
        for ( i=0; i<data->num_keys; i++ ) {
 
2836
                if ( strequal( data->keys[i].name, name ) ) {
 
2837
 
 
2838
                        /* cleanup memory */
 
2839
 
 
2840
                        TALLOC_FREE( data->keys[i].name );
 
2841
                        TALLOC_FREE( data->keys[i].values );
 
2842
 
 
2843
                        /* if not the end of the array, move remaining elements down one slot */
 
2844
 
 
2845
                        data->num_keys--;
 
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) );
 
2848
 
 
2849
                        break;
 
2850
                }
 
2851
        }
 
2852
 
 
2853
 
 
2854
        return data->num_keys;
 
2855
}
 
2856
 
 
2857
/****************************************************************************
 
2858
 search for a registry key name in the existing printer data
 
2859
 ***************************************************************************/
 
2860
 
 
2861
int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
 
2862
{
 
2863
        int             key_index = -1;
 
2864
        int             i;
 
2865
 
 
2866
        if ( !data || !name )
 
2867
                return -1;
 
2868
 
 
2869
        DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
 
2870
 
 
2871
        /* loop over all existing keys */
 
2872
 
 
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));
 
2876
                        key_index = i;
 
2877
                        break;
 
2878
 
 
2879
                }
 
2880
        }
 
2881
 
 
2882
        return key_index;
 
2883
}
 
2884
 
 
2885
/****************************************************************************
 
2886
 ***************************************************************************/
 
2887
 
 
2888
int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
 
2889
{
 
2890
        int     i, j;
 
2891
        int     key_len;
 
2892
        int     num_subkeys = 0;
 
2893
        char    *p;
 
2894
        fstring *subkeys_ptr = NULL;
 
2895
        fstring subkeyname;
 
2896
 
 
2897
        *subkeys = NULL;
 
2898
 
 
2899
        if ( !data )
 
2900
                return 0;
 
2901
 
 
2902
        if ( !key )
 
2903
                return -1;
 
2904
 
 
2905
        /* special case of asking for the top level printer data registry key names */
 
2906
 
 
2907
        if ( strlen(key) == 0 ) {
 
2908
                for ( i=0; i<data->num_keys; i++ ) {
 
2909
 
 
2910
                        /* found a match, so allocate space and copy the name */
 
2911
 
 
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",
 
2914
                                        num_subkeys+1));
 
2915
                                return -1;
 
2916
                        }
 
2917
 
 
2918
                        fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
 
2919
                        num_subkeys++;
 
2920
                }
 
2921
 
 
2922
                goto done;
 
2923
        }
 
2924
 
 
2925
        /* asking for the subkeys of some key */
 
2926
        /* subkey paths are stored in the key name using '\' as the delimiter */
 
2927
 
 
2928
        for ( i=0; i<data->num_keys; i++ ) {
 
2929
                if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
 
2930
 
 
2931
                        /* if we found the exact key, then break */
 
2932
                        key_len = strlen( key );
 
2933
                        if ( strlen(data->keys[i].name) == key_len )
 
2934
                                break;
 
2935
 
 
2936
                        /* get subkey path */
 
2937
 
 
2938
                        p = data->keys[i].name + key_len;
 
2939
                        if ( *p == '\\' )
 
2940
                                p++;
 
2941
                        fstrcpy( subkeyname, p );
 
2942
                        if ( (p = strchr( subkeyname, '\\' )) )
 
2943
                                *p = '\0';
 
2944
 
 
2945
                        /* don't add a key more than once */
 
2946
 
 
2947
                        for ( j=0; j<num_subkeys; j++ ) {
 
2948
                                if ( strequal( subkeys_ptr[j], subkeyname ) )
 
2949
                                        break;
 
2950
                        }
 
2951
 
 
2952
                        if ( j != num_subkeys )
 
2953
                                continue;
 
2954
 
 
2955
                        /* found a match, so allocate space and copy the name */
 
2956
 
 
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",
 
2959
                                        num_subkeys+1));
 
2960
                                return 0;
 
2961
                        }
 
2962
 
 
2963
                        fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
 
2964
                        num_subkeys++;
 
2965
                }
 
2966
 
 
2967
        }
 
2968
 
 
2969
        /* return error if the key was not found */
 
2970
 
 
2971
        if ( i == data->num_keys ) {
 
2972
                SAFE_FREE(subkeys_ptr);
 
2973
                return -1;
 
2974
        }
 
2975
 
 
2976
done:
 
2977
        /* tag off the end */
 
2978
 
 
2979
        if (num_subkeys)
 
2980
                fstrcpy(subkeys_ptr[num_subkeys], "" );
 
2981
 
 
2982
        *subkeys = subkeys_ptr;
 
2983
 
 
2984
        return num_subkeys;
 
2985
}
 
2986
 
 
2987
#ifdef HAVE_ADS
 
2988
static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
 
2989
                            const char *sz)
 
2990
{
 
2991
        smb_ucs2_t conv_str[1024];
 
2992
        size_t str_size;
 
2993
 
 
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);
 
2999
}
 
3000
 
 
3001
static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
 
3002
                               uint32 dword)
 
3003
{
 
3004
        regval_ctr_delvalue(ctr, val_name);
 
3005
        regval_ctr_addvalue(ctr, val_name, REG_DWORD,
 
3006
                            (char *) &dword, sizeof(dword));
 
3007
}
 
3008
 
 
3009
static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
 
3010
                              bool b)
 
3011
{
 
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));
 
3016
}
 
3017
 
 
3018
static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
 
3019
                                         const char *multi_sz)
 
3020
{
 
3021
        smb_ucs2_t *conv_strs = NULL;
 
3022
        size_t str_size;
 
3023
 
 
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);
 
3028
        if (!conv_strs) {
 
3029
                return;
 
3030
        }
 
3031
 
 
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);
 
3036
 
 
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);
 
3041
}
 
3042
 
 
3043
/****************************************************************************
 
3044
 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
 
3045
 *
 
3046
 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
 
3047
 * @return bool indicating success or failure
 
3048
 ***************************************************************************/
 
3049
 
 
3050
static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
 
3051
{
 
3052
        REGVAL_CTR *ctr = NULL;
 
3053
        fstring longname;
 
3054
        const char *dnssuffix;
 
3055
        char *allocated_string = NULL;
 
3056
        const char *ascii_str;
 
3057
        int i;
 
3058
 
 
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;
 
3062
 
 
3063
        map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
 
3064
        map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
 
3065
 
 
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
 
3068
           join the domain */
 
3069
 
 
3070
        dnssuffix = get_mydnsdomname(talloc_tos());
 
3071
        if (dnssuffix && *dnssuffix) {
 
3072
                fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
 
3073
        } else {
 
3074
                fstrcpy( longname, global_myname() );
 
3075
        }
 
3076
 
 
3077
        map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
 
3078
 
 
3079
        if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
 
3080
                return false;
 
3081
        }
 
3082
        map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
 
3083
        SAFE_FREE(allocated_string);
 
3084
 
 
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);
 
3094
 
 
3095
        map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
 
3096
                          (info2->attributes &
 
3097
                           PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
 
3098
 
 
3099
        switch (info2->attributes & 0x3) {
 
3100
        case 0:
 
3101
                ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
 
3102
                break;
 
3103
        case 1:
 
3104
                ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
 
3105
                break;
 
3106
        case 2:
 
3107
                ascii_str = SPOOL_REGVAL_PRINTDIRECT;
 
3108
                break;
 
3109
        default:
 
3110
                ascii_str = "unknown";
 
3111
        }
 
3112
        map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
 
3113
 
 
3114
        return True;
 
3115
}
 
3116
 
 
3117
/*****************************************************************
 
3118
 ****************************************************************/
 
3119
 
 
3120
static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
 
3121
                               struct GUID guid)
 
3122
{
 
3123
        int i;
 
3124
        REGVAL_CTR *ctr=NULL;
 
3125
        UNISTR2 unistr_guid;
 
3126
 
 
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;
 
3131
 
 
3132
        regval_ctr_delvalue(ctr, "objectGUID");
 
3133
 
 
3134
        /* We used to store this as a REG_BINARY but that causes
 
3135
           Vista to whine */
 
3136
 
 
3137
        ZERO_STRUCT( unistr_guid );
 
3138
 
 
3139
        init_unistr2( &unistr_guid, GUID_string(talloc_tos(), &guid),
 
3140
                      UNI_STR_TERMINATE );
 
3141
 
 
3142
        regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
 
3143
                            (char *)unistr_guid.buffer,
 
3144
                            unistr_guid.uni_max_len*2);
 
3145
 
 
3146
}
 
3147
 
 
3148
static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
 
3149
                                     NT_PRINTER_INFO_LEVEL *printer)
 
3150
{
 
3151
        ADS_STATUS ads_rc;
 
3152
        LDAPMessage *res;
 
3153
        char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
 
3154
        char *srv_dn_utf8, **srv_cn_utf8;
 
3155
        TALLOC_CTX *ctx;
 
3156
        ADS_MODLIST mods;
 
3157
        const char *attrs[] = {"objectGUID", NULL};
 
3158
        struct GUID guid;
 
3159
        WERROR win_rc = WERR_OK;
 
3160
        size_t converted_size;
 
3161
 
 
3162
        /* build the ads mods */
 
3163
        ctx = talloc_init("nt_printer_publish_ads");
 
3164
        if (ctx == NULL) {
 
3165
                return WERR_NOMEM;
 
3166
        }
 
3167
 
 
3168
        DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
 
3169
 
 
3170
        /* figure out where to publish */
 
3171
        ads_find_machine_acct(ads, &res, global_myname());
 
3172
 
 
3173
        /* We use ldap_get_dn here as we need the answer
 
3174
         * in utf8 to call ldap_explode_dn(). JRA. */
 
3175
 
 
3176
        srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
 
3177
        if (!srv_dn_utf8) {
 
3178
                TALLOC_FREE(ctx);
 
3179
                return WERR_SERVER_UNAVAILABLE;
 
3180
        }
 
3181
        ads_msgfree(ads, res);
 
3182
        srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
 
3183
        if (!srv_cn_utf8) {
 
3184
                TALLOC_FREE(ctx);
 
3185
                ldap_memfree(srv_dn_utf8);
 
3186
                return WERR_SERVER_UNAVAILABLE;
 
3187
        }
 
3188
        /* Now convert to CH_UNIX. */
 
3189
        if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
 
3190
                TALLOC_FREE(ctx);
 
3191
                ldap_memfree(srv_dn_utf8);
 
3192
                ldap_memfree(srv_cn_utf8);
 
3193
                return WERR_SERVER_UNAVAILABLE;
 
3194
        }
 
3195
        if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
 
3196
                TALLOC_FREE(ctx);
 
3197
                ldap_memfree(srv_dn_utf8);
 
3198
                ldap_memfree(srv_cn_utf8);
 
3199
                TALLOC_FREE(srv_dn);
 
3200
                return WERR_SERVER_UNAVAILABLE;
 
3201
        }
 
3202
 
 
3203
        ldap_memfree(srv_dn_utf8);
 
3204
        ldap_memfree(srv_cn_utf8);
 
3205
 
 
3206
        srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
 
3207
        if (!srv_cn_escaped) {
 
3208
                TALLOC_FREE(ctx);
 
3209
                return WERR_SERVER_UNAVAILABLE;
 
3210
        }
 
3211
        sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
 
3212
        if (!sharename_escaped) {
 
3213
                SAFE_FREE(srv_cn_escaped);
 
3214
                TALLOC_FREE(ctx);
 
3215
                return WERR_SERVER_UNAVAILABLE;
 
3216
        }
 
3217
 
 
3218
        prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
 
3219
 
 
3220
        SAFE_FREE(srv_cn_escaped);
 
3221
        SAFE_FREE(sharename_escaped);
 
3222
 
 
3223
        mods = ads_init_mods(ctx);
 
3224
 
 
3225
        if (mods == NULL) {
 
3226
                SAFE_FREE(prt_dn);
 
3227
                TALLOC_FREE(ctx);
 
3228
                return WERR_NOMEM;
 
3229
        }
 
3230
 
 
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);
 
3234
 
 
3235
        /* publish it */
 
3236
        ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
 
3237
        if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
 
3238
                int i;
 
3239
                for (i=0; mods[i] != 0; i++)
 
3240
                        ;
 
3241
                mods[i] = (LDAPMod *)-1;
 
3242
                ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
 
3243
        }
 
3244
 
 
3245
        if (!ADS_ERR_OK(ads_rc))
 
3246
                DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
 
3247
 
 
3248
        /* retreive the guid and store it locally */
 
3249
        if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
 
3250
                ZERO_STRUCT(guid);
 
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);
 
3255
        }
 
3256
        TALLOC_FREE(ctx);
 
3257
 
 
3258
        return win_rc;
 
3259
}
 
3260
 
 
3261
static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
 
3262
                                       NT_PRINTER_INFO_LEVEL *printer)
 
3263
{
 
3264
        ADS_STATUS ads_rc;
 
3265
        LDAPMessage *res = NULL;
 
3266
        char *prt_dn = NULL;
 
3267
 
 
3268
        DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
 
3269
 
 
3270
        /* remove the printer from the directory */
 
3271
        ads_rc = ads_find_printer_on_server(ads, &res,
 
3272
                            printer->info_2->sharename, global_myname());
 
3273
 
 
3274
        if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
 
3275
                prt_dn = ads_get_dn(ads, talloc_tos(), res);
 
3276
                if (!prt_dn) {
 
3277
                        ads_msgfree(ads, res);
 
3278
                        return WERR_NOMEM;
 
3279
                }
 
3280
                ads_rc = ads_del_dn(ads, prt_dn);
 
3281
                TALLOC_FREE(prt_dn);
 
3282
        }
 
3283
 
 
3284
        if (res) {
 
3285
                ads_msgfree(ads, res);
 
3286
        }
 
3287
        return WERR_OK;
 
3288
}
 
3289
 
 
3290
/****************************************************************************
 
3291
 * Publish a printer in the directory
 
3292
 *
 
3293
 * @param snum describing printer service
 
3294
 * @return WERROR indicating status of publishing
 
3295
 ***************************************************************************/
 
3296
 
 
3297
WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
 
3298
{
 
3299
        ADS_STATUS ads_rc;
 
3300
        ADS_STRUCT *ads = NULL;
 
3301
        NT_PRINTER_INFO_LEVEL *printer = NULL;
 
3302
        WERROR win_rc;
 
3303
 
 
3304
        win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
 
3305
        if (!W_ERROR_IS_OK(win_rc))
 
3306
                goto done;
 
3307
 
 
3308
        switch (action) {
 
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;
 
3314
                        goto done;
 
3315
                }
 
3316
 
 
3317
                printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
 
3318
                break;
 
3319
        case DSPRINT_UNPUBLISH:
 
3320
                printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
 
3321
                break;
 
3322
        default:
 
3323
                win_rc = WERR_NOT_SUPPORTED;
 
3324
                goto done;
 
3325
        }
 
3326
 
 
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)));
 
3330
                goto done;
 
3331
        }
 
3332
 
 
3333
        ads = ads_init(lp_realm(), lp_workgroup(), NULL);
 
3334
        if (!ads) {
 
3335
                DEBUG(3, ("ads_init() failed\n"));
 
3336
                win_rc = WERR_SERVER_UNAVAILABLE;
 
3337
                goto done;
 
3338
        }
 
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(),
 
3342
                NULL, NULL);
 
3343
 
 
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;
 
3349
                goto done;
 
3350
        }
 
3351
 
 
3352
        switch (action) {
 
3353
        case DSPRINT_PUBLISH:
 
3354
        case DSPRINT_UPDATE:
 
3355
                win_rc = nt_printer_publish_ads(ads, printer);
 
3356
                break;
 
3357
        case DSPRINT_UNPUBLISH:
 
3358
                win_rc = nt_printer_unpublish_ads(ads, printer);
 
3359
                break;
 
3360
        }
 
3361
 
 
3362
done:
 
3363
        free_a_printer(&printer, 2);
 
3364
        ads_destroy(&ads);
 
3365
        return win_rc;
 
3366
}
 
3367
 
 
3368
WERROR check_published_printers(void)
 
3369
{
 
3370
        ADS_STATUS ads_rc;
 
3371
        ADS_STRUCT *ads = NULL;
 
3372
        int snum;
 
3373
        int n_services = lp_numservices();
 
3374
        NT_PRINTER_INFO_LEVEL *printer = NULL;
 
3375
 
 
3376
        ads = ads_init(lp_realm(), lp_workgroup(), NULL);
 
3377
        if (!ads) {
 
3378
                DEBUG(3, ("ads_init() failed\n"));
 
3379
                return WERR_SERVER_UNAVAILABLE;
 
3380
        }
 
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(),
 
3384
                NULL, NULL);
 
3385
 
 
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)));
 
3390
                ads_destroy(&ads);
 
3391
                ads_kdestroy("MEMORY:prtpub_cache");
 
3392
                return WERR_ACCESS_DENIED;
 
3393
        }
 
3394
 
 
3395
        for (snum = 0; snum < n_services; snum++) {
 
3396
                if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
 
3397
                        continue;
 
3398
 
 
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);
 
3403
 
 
3404
                free_a_printer(&printer, 2);
 
3405
        }
 
3406
 
 
3407
        ads_destroy(&ads);
 
3408
        ads_kdestroy("MEMORY:prtpub_cache");
 
3409
        return WERR_OK;
 
3410
}
 
3411
 
 
3412
bool is_printer_published(Printer_entry *print_hnd, int snum,
 
3413
                          struct GUID *guid)
 
3414
{
 
3415
        NT_PRINTER_INFO_LEVEL *printer = NULL;
 
3416
        REGVAL_CTR *ctr;
 
3417
        REGISTRY_VALUE *guid_val;
 
3418
        WERROR win_rc;
 
3419
        int i;
 
3420
        bool ret = False;
 
3421
 
 
3422
        win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
 
3423
 
 
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")))
 
3429
        {
 
3430
                free_a_printer(&printer, 2);
 
3431
                return False;
 
3432
        }
 
3433
 
 
3434
        /* fetching printer guids really ought to be a separate function. */
 
3435
 
 
3436
        if ( guid ) {
 
3437
                fstring guid_str;
 
3438
 
 
3439
                /* We used to store the guid as REG_BINARY, then swapped
 
3440
                   to REG_SZ for Vista compatibility so check for both */
 
3441
 
 
3442
                switch ( regval_type(guid_val) ){
 
3443
                case REG_SZ:
 
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 ));
 
3447
                        break;
 
3448
                case REG_BINARY:
 
3449
                        if ( regval_size(guid_val) != sizeof(struct GUID) ) {
 
3450
                                ret = False;
 
3451
                                break;
 
3452
                        }
 
3453
                        memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
 
3454
                        break;
 
3455
                default:
 
3456
                        DEBUG(0,("is_printer_published: GUID value stored as "
 
3457
                                 "invaluid type (%d)\n", regval_type(guid_val) ));
 
3458
                        break;
 
3459
                }
 
3460
        }
 
3461
 
 
3462
        free_a_printer(&printer, 2);
 
3463
        return ret;
 
3464
}
 
3465
#else
 
3466
WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
 
3467
{
 
3468
        return WERR_OK;
 
3469
}
 
3470
 
 
3471
WERROR check_published_printers(void)
 
3472
{
 
3473
        return WERR_OK;
 
3474
}
 
3475
 
 
3476
bool is_printer_published(Printer_entry *print_hnd, int snum,
 
3477
                          struct GUID *guid)
 
3478
{
 
3479
        return False;
 
3480
}
 
3481
#endif /* HAVE_ADS */
 
3482
 
 
3483
/****************************************************************************
 
3484
 ***************************************************************************/
 
3485
 
 
3486
WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
 
3487
{
 
3488
        NT_PRINTER_DATA *data;
 
3489
        int             i;
 
3490
        int             removed_keys = 0;
 
3491
        int             empty_slot;
 
3492
 
 
3493
        data = p2->data;
 
3494
        empty_slot = data->num_keys;
 
3495
 
 
3496
        if ( !key )
 
3497
                return WERR_INVALID_PARAM;
 
3498
 
 
3499
        /* remove all keys */
 
3500
 
 
3501
        if ( !strlen(key) ) {
 
3502
 
 
3503
                TALLOC_FREE( data );
 
3504
 
 
3505
                p2->data = NULL;
 
3506
 
 
3507
                DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
 
3508
                        p2->printername ));
 
3509
 
 
3510
                return WERR_OK;
 
3511
        }
 
3512
 
 
3513
        /* remove a specific key (and all subkeys) */
 
3514
 
 
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));
 
3519
 
 
3520
                        TALLOC_FREE( data->keys[i].name );
 
3521
                        TALLOC_FREE( data->keys[i].values );
 
3522
 
 
3523
                        /* mark the slot as empty */
 
3524
 
 
3525
                        ZERO_STRUCTP( &data->keys[i] );
 
3526
                }
 
3527
        }
 
3528
 
 
3529
        /* find the first empty slot */
 
3530
 
 
3531
        for ( i=0; i<data->num_keys; i++ ) {
 
3532
                if ( !data->keys[i].name ) {
 
3533
                        empty_slot = i;
 
3534
                        removed_keys++;
 
3535
                        break;
 
3536
                }
 
3537
        }
 
3538
 
 
3539
        if ( i == data->num_keys )
 
3540
                /* nothing was removed */
 
3541
                return WERR_INVALID_PARAM;
 
3542
 
 
3543
        /* move everything down */
 
3544
 
 
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] );
 
3549
                        empty_slot++;
 
3550
                        removed_keys++;
 
3551
                }
 
3552
        }
 
3553
 
 
3554
        /* update count */
 
3555
 
 
3556
        data->num_keys -= removed_keys;
 
3557
 
 
3558
        /* sanity check to see if anything is left */
 
3559
 
 
3560
        if ( !data->num_keys ) {
 
3561
                DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
 
3562
 
 
3563
                SAFE_FREE( data->keys );
 
3564
                ZERO_STRUCTP( data );
 
3565
        }
 
3566
 
 
3567
        return WERR_OK;
 
3568
}
 
3569
 
 
3570
/****************************************************************************
 
3571
 ***************************************************************************/
 
3572
 
 
3573
WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
 
3574
{
 
3575
        WERROR          result = WERR_OK;
 
3576
        int             key_index;
 
3577
 
 
3578
        /* we must have names on non-zero length */
 
3579
 
 
3580
        if ( !key || !*key|| !value || !*value )
 
3581
                return WERR_INVALID_NAME;
 
3582
 
 
3583
        /* find the printer key first */
 
3584
 
 
3585
        key_index = lookup_printerkey( p2->data, key );
 
3586
        if ( key_index == -1 )
 
3587
                return WERR_OK;
 
3588
 
 
3589
        /* make sure the value exists so we can return the correct error code */
 
3590
 
 
3591
        if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
 
3592
                return WERR_BADFILE;
 
3593
 
 
3594
        regval_ctr_delvalue( p2->data->keys[key_index].values, value );
 
3595
 
 
3596
        DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
 
3597
                key, value ));
 
3598
 
 
3599
        return result;
 
3600
}
 
3601
 
 
3602
/****************************************************************************
 
3603
 ***************************************************************************/
 
3604
 
 
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 )
 
3607
{
 
3608
        WERROR          result = WERR_OK;
 
3609
        int             key_index;
 
3610
 
 
3611
        /* we must have names on non-zero length */
 
3612
 
 
3613
        if ( !key || !*key|| !value || !*value )
 
3614
                return WERR_INVALID_NAME;
 
3615
 
 
3616
        /* find the printer key first */
 
3617
 
 
3618
        key_index = lookup_printerkey( p2->data, key );
 
3619
        if ( key_index == -1 )
 
3620
                key_index = add_new_printer_key( p2->data, key );
 
3621
 
 
3622
        if ( key_index == -1 )
 
3623
                return WERR_NOMEM;
 
3624
 
 
3625
        regval_ctr_addvalue( p2->data->keys[key_index].values, value,
 
3626
                type, (const char *)data, real_len );
 
3627
 
 
3628
        DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
 
3629
                key, value, type, real_len  ));
 
3630
 
 
3631
        return result;
 
3632
}
 
3633
 
 
3634
/****************************************************************************
 
3635
 ***************************************************************************/
 
3636
 
 
3637
REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
 
3638
{
 
3639
        int             key_index;
 
3640
 
 
3641
        if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
 
3642
                return NULL;
 
3643
 
 
3644
        DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
 
3645
                key, value ));
 
3646
 
 
3647
        return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
 
3648
}
 
3649
 
 
3650
/****************************************************************************
 
3651
 Unpack a list of registry values frem the TDB
 
3652
 ***************************************************************************/
 
3653
 
 
3654
static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
 
3655
{
 
3656
        int             len = 0;
 
3657
        uint32          type;
 
3658
        fstring string;
 
3659
        const char *valuename = NULL;
 
3660
        const char *keyname = NULL;
 
3661
        char            *str;
 
3662
        int             size;
 
3663
        uint8           *data_p;
 
3664
        REGISTRY_VALUE  *regval_p;
 
3665
        int             key_index;
 
3666
 
 
3667
        /* add the "PrinterDriverData" key first for performance reasons */
 
3668
 
 
3669
        add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
 
3670
 
 
3671
        /* loop and unpack the rest of the registry values */
 
3672
 
 
3673
        while ( True ) {
 
3674
 
 
3675
                /* check to see if there are any more registry values */
 
3676
 
 
3677
                regval_p = NULL;
 
3678
                len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
 
3679
                if ( !regval_p )
 
3680
                        break;
 
3681
 
 
3682
                /* unpack the next regval */
 
3683
 
 
3684
                len += tdb_unpack(buf+len, buflen-len, "fdB",
 
3685
                                  string,
 
3686
                                  &type,
 
3687
                                  &size,
 
3688
                                  &data_p);
 
3689
 
 
3690
                /* lookup for subkey names which have a type of REG_NONE */
 
3691
                /* there's no data with this entry */
 
3692
 
 
3693
                if ( type == REG_NONE ) {
 
3694
                        if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
 
3695
                                add_new_printer_key( printer_data, string );
 
3696
                        continue;
 
3697
                }
 
3698
 
 
3699
                /*
 
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.
 
3704
                 * -- jerry
 
3705
                 */
 
3706
 
 
3707
                str = strchr_m( string, '\\');
 
3708
 
 
3709
                /* Put in "PrinterDriverData" is no key specified */
 
3710
 
 
3711
                if ( !str ) {
 
3712
                        keyname = SPOOL_PRINTERDATA_KEY;
 
3713
                        valuename = string;
 
3714
                }
 
3715
                else {
 
3716
                        *str = '\0';
 
3717
                        keyname = string;
 
3718
                        valuename = str+1;
 
3719
                }
 
3720
 
 
3721
                /* see if we need a new key */
 
3722
 
 
3723
                if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
 
3724
                        key_index = add_new_printer_key( printer_data, keyname );
 
3725
 
 
3726
                if ( key_index == -1 ) {
 
3727
                        DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
 
3728
                                keyname));
 
3729
                        break;
 
3730
                }
 
3731
 
 
3732
                DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
 
3733
 
 
3734
                /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
 
3735
                   Thanks to Martin Zielinski for the hint. */
 
3736
 
 
3737
                if ( type == REG_BINARY &&
 
3738
                     strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
 
3739
                     strequal( valuename, "objectGUID" ) )
 
3740
                {
 
3741
                        struct GUID guid;
 
3742
                        UNISTR2 unistr_guid;
 
3743
 
 
3744
                        ZERO_STRUCT( unistr_guid );
 
3745
 
 
3746
                        /* convert the GUID to a UNICODE string */
 
3747
 
 
3748
                        memcpy( &guid, data_p, sizeof(struct GUID) );
 
3749
 
 
3750
                        init_unistr2( &unistr_guid,
 
3751
                                      GUID_string(talloc_tos(), &guid),
 
3752
                                      UNI_STR_TERMINATE );
 
3753
 
 
3754
                        regval_ctr_addvalue( printer_data->keys[key_index].values,
 
3755
                                             valuename, REG_SZ,
 
3756
                                             (const char *)unistr_guid.buffer,
 
3757
                                             unistr_guid.uni_str_len*2 );
 
3758
 
 
3759
                } else {
 
3760
                        /* add the value */
 
3761
 
 
3762
                        regval_ctr_addvalue( printer_data->keys[key_index].values,
 
3763
                                             valuename, type, (const char *)data_p,
 
3764
                                             size );
 
3765
                }
 
3766
 
 
3767
                SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
 
3768
 
 
3769
        }
 
3770
 
 
3771
        return len;
 
3772
}
 
3773
 
 
3774
/****************************************************************************
 
3775
 ***************************************************************************/
 
3776
 
 
3777
static char *last_from;
 
3778
static char *last_to;
 
3779
 
 
3780
static const char *get_last_from(void)
 
3781
{
 
3782
        if (!last_from) {
 
3783
                return "";
 
3784
        }
 
3785
        return last_from;
 
3786
}
 
3787
 
 
3788
static const char *get_last_to(void)
 
3789
{
 
3790
        if (!last_to) {
 
3791
                return "";
 
3792
        }
 
3793
        return last_to;
 
3794
}
 
3795
 
 
3796
static bool set_last_from_to(const char *from, const char *to)
 
3797
{
 
3798
        char *orig_from = last_from;
 
3799
        char *orig_to = last_to;
 
3800
 
 
3801
        last_from = SMB_STRDUP(from);
 
3802
        last_to = SMB_STRDUP(to);
 
3803
 
 
3804
        SAFE_FREE(orig_from);
 
3805
        SAFE_FREE(orig_to);
 
3806
 
 
3807
        if (!last_from || !last_to) {
 
3808
                SAFE_FREE(last_from);
 
3809
                SAFE_FREE(last_to);
 
3810
                return false;
 
3811
        }
 
3812
        return true;
 
3813
}
 
3814
 
 
3815
static void map_to_os2_driver(fstring drivername)
 
3816
{
 
3817
        char *mapfile = lp_os2_driver_map();
 
3818
        char **lines = NULL;
 
3819
        int numlines = 0;
 
3820
        int i;
 
3821
 
 
3822
        if (!strlen(drivername))
 
3823
                return;
 
3824
 
 
3825
        if (!*mapfile)
 
3826
                return;
 
3827
 
 
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());
 
3832
                return;
 
3833
        }
 
3834
 
 
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));
 
3838
                TALLOC_FREE(lines);
 
3839
                return;
 
3840
        }
 
3841
 
 
3842
        DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
 
3843
 
 
3844
        for( i = 0; i < numlines; i++) {
 
3845
                char *nt_name = lines[i];
 
3846
                char *os2_name = strchr(nt_name,'=');
 
3847
 
 
3848
                if (!os2_name)
 
3849
                        continue;
 
3850
 
 
3851
                *os2_name++ = 0;
 
3852
 
 
3853
                while (isspace(*nt_name))
 
3854
                        nt_name++;
 
3855
 
 
3856
                if (!*nt_name || strchr("#;",*nt_name))
 
3857
                        continue;
 
3858
 
 
3859
                {
 
3860
                        int l = strlen(nt_name);
 
3861
                        while (l && isspace(nt_name[l-1])) {
 
3862
                                nt_name[l-1] = 0;
 
3863
                                l--;
 
3864
                        }
 
3865
                }
 
3866
 
 
3867
                while (isspace(*os2_name))
 
3868
                        os2_name++;
 
3869
 
 
3870
                {
 
3871
                        int l = strlen(os2_name);
 
3872
                        while (l && isspace(os2_name[l-1])) {
 
3873
                                os2_name[l-1] = 0;
 
3874
                                l--;
 
3875
                        }
 
3876
                }
 
3877
 
 
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);
 
3882
                        TALLOC_FREE(lines);
 
3883
                        return;
 
3884
                }
 
3885
        }
 
3886
 
 
3887
        TALLOC_FREE(lines);
 
3888
}
 
3889
 
 
3890
/****************************************************************************
 
3891
 Get a default printer info 2 struct.
 
3892
****************************************************************************/
 
3893
 
 
3894
static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
 
3895
                                const char *servername,
 
3896
                                const char* sharename,
 
3897
                                bool get_loc_com)
 
3898
{
 
3899
        int snum = lp_servicenumber(sharename);
 
3900
 
 
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);
 
3906
 
 
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");
 
3914
#endif
 
3915
 
 
3916
 
 
3917
        DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
 
3918
 
 
3919
        strlcpy(info->comment, "", sizeof(info->comment));
 
3920
        fstrcpy(info->printprocessor, "winprint");
 
3921
        fstrcpy(info->datatype, "RAW");
 
3922
 
 
3923
#ifdef HAVE_CUPS
 
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
 
3926
                   already have one */
 
3927
                if ( !strlen(info->location) || !strlen(info->comment) )
 
3928
                        cups_pull_comment_location( info );
 
3929
        }
 
3930
#endif
 
3931
 
 
3932
        info->attributes = PRINTER_ATTRIBUTE_SAMBA;
 
3933
 
 
3934
        info->starttime = 0; /* Minutes since 12:00am GMT */
 
3935
        info->untiltime = 0; /* Minutes since 12:00am GMT */
 
3936
        info->priority = 1;
 
3937
        info->default_priority = 1;
 
3938
        info->setuptime = (uint32)time(NULL);
 
3939
 
 
3940
        /*
 
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.
 
3944
         *
 
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
 
3948
         */
 
3949
 
 
3950
        if (lp_default_devmode(snum)) {
 
3951
                if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
 
3952
                        goto fail;
 
3953
                }
 
3954
        } else {
 
3955
                info->devmode = NULL;
 
3956
        }
 
3957
 
 
3958
        if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
 
3959
                goto fail;
 
3960
        }
 
3961
 
 
3962
        return WERR_OK;
 
3963
 
 
3964
fail:
 
3965
        if (info->devmode)
 
3966
                free_nt_devicemode(&info->devmode);
 
3967
 
 
3968
        return WERR_ACCESS_DENIED;
 
3969
}
 
3970
 
 
3971
/****************************************************************************
 
3972
****************************************************************************/
 
3973
 
 
3974
static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
 
3975
                                const char *servername,
 
3976
                                const char *sharename,
 
3977
                                bool get_loc_com)
 
3978
{
 
3979
        int len = 0;
 
3980
        int snum = lp_servicenumber(sharename);
 
3981
        TDB_DATA kbuf, dbuf;
 
3982
        fstring printername;
 
3983
        char adevice[MAXDEVICENAME];
 
3984
        char *comment = NULL;
 
3985
 
 
3986
        kbuf = make_printer_tdbkey(talloc_tos(), sharename);
 
3987
 
 
3988
        dbuf = tdb_fetch(tdb_printers, kbuf);
 
3989
        if (!dbuf.dptr) {
 
3990
                return get_a_printer_2_default(info, servername,
 
3991
                                        sharename, get_loc_com);
 
3992
        }
 
3993
 
 
3994
        len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
 
3995
                        &info->attributes,
 
3996
                        &info->priority,
 
3997
                        &info->default_priority,
 
3998
                        &info->starttime,
 
3999
                        &info->untiltime,
 
4000
                        &info->status,
 
4001
                        &info->cjobs,
 
4002
                        &info->averageppm,
 
4003
                        &info->changeid,
 
4004
                        &info->c_setprinter,
 
4005
                        &info->setuptime,
 
4006
                        info->servername,
 
4007
                        info->printername,
 
4008
                        info->sharename,
 
4009
                        info->portname,
 
4010
                        info->drivername,
 
4011
                        &comment,
 
4012
                        info->location,
 
4013
                        info->sepfile,
 
4014
                        info->printprocessor,
 
4015
                        info->datatype,
 
4016
                        info->parameters);
 
4017
 
 
4018
        if (comment) {
 
4019
                strlcpy(info->comment, comment, sizeof(info->comment));
 
4020
                SAFE_FREE(comment);
 
4021
        }
 
4022
 
 
4023
        /* Samba has to have shared raw drivers. */
 
4024
        info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
 
4025
        info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
 
4026
 
 
4027
        /* Restore the stripped strings. */
 
4028
        slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
 
4029
 
 
4030
        if ( lp_force_printername(snum) ) {
 
4031
                slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
 
4032
        } else {
 
4033
                slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
 
4034
        }
 
4035
 
 
4036
        fstrcpy(info->printername, printername);
 
4037
 
 
4038
#ifdef HAVE_CUPS
 
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
 
4041
                   already have one */
 
4042
                if ( !strlen(info->location) || !strlen(info->comment) )
 
4043
                        cups_pull_comment_location( info );
 
4044
        }
 
4045
#endif
 
4046
 
 
4047
        len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
 
4048
 
 
4049
        /*
 
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
 
4053
         *
 
4054
         * See comments in get_a_printer_2_default()
 
4055
         */
 
4056
 
 
4057
        if (lp_default_devmode(snum) && !info->devmode) {
 
4058
                DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
 
4059
                        printername));
 
4060
                info->devmode = construct_nt_devicemode(printername);
 
4061
        }
 
4062
 
 
4063
        slprintf( adevice, sizeof(adevice), "%s", info->printername );
 
4064
        if (info->devmode) {
 
4065
                fstrcpy(info->devmode->devicename, adevice);
 
4066
        }
 
4067
 
 
4068
        if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
 
4069
                DEBUG(0,("unpack_values: talloc() failed!\n"));
 
4070
                SAFE_FREE(dbuf.dptr);
 
4071
                return WERR_NOMEM;
 
4072
        }
 
4073
        len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
 
4074
 
 
4075
        /* This will get the current RPC talloc context, but we should be
 
4076
           passing this as a parameter... fixme... JRA ! */
 
4077
 
 
4078
        if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
 
4079
                SAFE_FREE(dbuf.dptr);
 
4080
                return WERR_NOMEM;
 
4081
        }
 
4082
 
 
4083
        /* Fix for OS/2 drivers. */
 
4084
 
 
4085
        if (get_remote_arch() == RA_OS2) {
 
4086
                map_to_os2_driver(info->drivername);
 
4087
        }
 
4088
 
 
4089
        SAFE_FREE(dbuf.dptr);
 
4090
 
 
4091
        DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
 
4092
                 sharename, info->printername, info->drivername));
 
4093
 
 
4094
        return WERR_OK;
 
4095
}
 
4096
 
 
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)
 
4101
{
 
4102
        uint32 result;
 
4103
        NT_PRINTER_INFO_LEVEL_2 *info2;
 
4104
 
 
4105
        DEBUG(106,("Dumping printer at level [%d]\n", level));
 
4106
 
 
4107
        switch (level) {
 
4108
                case 2:
 
4109
                {
 
4110
                        if (printer->info_2 == NULL)
 
4111
                                result=5;
 
4112
                        else
 
4113
                        {
 
4114
                                info2=printer->info_2;
 
4115
 
 
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));
 
4127
 
 
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));
 
4139
                                result=0;
 
4140
                        }
 
4141
                        break;
 
4142
                }
 
4143
                default:
 
4144
                        DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
 
4145
                        result=1;
 
4146
                        break;
 
4147
        }
 
4148
 
 
4149
        return result;
 
4150
}
 
4151
 
 
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
 
4157
 UTAH ! JRA.
 
4158
****************************************************************************/
 
4159
 
 
4160
static uint32 rev_changeid(void)
 
4161
{
 
4162
        struct timeval tv;
 
4163
 
 
4164
        get_process_uptime(&tv);
 
4165
 
 
4166
#if 1   /* JERRY */
 
4167
        /* Return changeid as msec since spooler restart */
 
4168
        return tv.tv_sec * 1000 + tv.tv_usec / 1000;
 
4169
#else
 
4170
        /*
 
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)
 
4174
         */
 
4175
        return tv.tv_sec * 10 + tv.tv_usec / 100000;
 
4176
#endif
 
4177
}
 
4178
 
 
4179
 
 
4180
/*
 
4181
 * The function below are the high level ones.
 
4182
 * only those ones must be called from the spoolss code.
 
4183
 * JFM.
 
4184
 */
 
4185
 
 
4186
/****************************************************************************
 
4187
 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
 
4188
****************************************************************************/
 
4189
 
 
4190
WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
 
4191
{
 
4192
        WERROR result;
 
4193
 
 
4194
        dump_a_printer(printer, level);
 
4195
 
 
4196
        switch (level) {
 
4197
                case 2:
 
4198
                {
 
4199
                        /*
 
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).
 
4203
                         */
 
4204
 
 
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 */
 
4208
 
 
4209
                        printer->info_2->changeid = rev_changeid();
 
4210
 
 
4211
                        /*
 
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
 
4216
                         *
 
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.
 
4223
                         *
 
4224
                         *              This is fixed in Win2k.  admin/non-admin
 
4225
                         *              connections both display changes immediately.
 
4226
                         *
 
4227
                         * 14/12/01     --jerry
 
4228
                         */
 
4229
 
 
4230
                        result=update_a_printer_2(printer->info_2);
 
4231
                        break;
 
4232
                }
 
4233
                default:
 
4234
                        result=WERR_UNKNOWN_LEVEL;
 
4235
                        break;
 
4236
        }
 
4237
 
 
4238
        return result;
 
4239
}
 
4240
 
 
4241
/****************************************************************************
 
4242
 Initialize printer devmode & data with previously saved driver init values.
 
4243
****************************************************************************/
 
4244
 
 
4245
static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
 
4246
{
 
4247
        int                     len = 0;
 
4248
        char *key = NULL;
 
4249
        TDB_DATA                dbuf;
 
4250
        NT_PRINTER_INFO_LEVEL_2 info;
 
4251
 
 
4252
 
 
4253
        ZERO_STRUCT(info);
 
4254
 
 
4255
        /*
 
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).
 
4259
         */
 
4260
 
 
4261
        if ( info_ptr->data )
 
4262
                delete_all_printer_data( info_ptr, "" );
 
4263
 
 
4264
        if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
 
4265
                                info_ptr->drivername) < 0) {
 
4266
                return false;
 
4267
        }
 
4268
 
 
4269
        dbuf = tdb_fetch_bystring(tdb_drivers, key);
 
4270
        if (!dbuf.dptr) {
 
4271
                /*
 
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.
 
4274
                 */
 
4275
                free_nt_devicemode(&info_ptr->devmode);
 
4276
                SAFE_FREE(key);
 
4277
                return false;
 
4278
        }
 
4279
 
 
4280
        SAFE_FREE(key);
 
4281
        /*
 
4282
         * Get the saved DEVMODE..
 
4283
         */
 
4284
 
 
4285
        len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
 
4286
 
 
4287
        /*
 
4288
         * The saved DEVMODE contains the devicename from the printer used during
 
4289
         * the initialization save. Change it to reflect the new printer.
 
4290
         */
 
4291
 
 
4292
        if ( info.devmode ) {
 
4293
                ZERO_STRUCT(info.devmode->devicename);
 
4294
                fstrcpy(info.devmode->devicename, info_ptr->printername);
 
4295
        }
 
4296
 
 
4297
        /*
 
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)
 
4301
         *
 
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.
 
4305
         * --jerry
 
4306
         */
 
4307
 
 
4308
 
 
4309
        /* Bind the saved DEVMODE to the new the printer */
 
4310
 
 
4311
        free_nt_devicemode(&info_ptr->devmode);
 
4312
        info_ptr->devmode = info.devmode;
 
4313
 
 
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));
 
4316
 
 
4317
        /* Add the printer data 'values' to the new printer */
 
4318
 
 
4319
        if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
 
4320
                DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
 
4321
                return False;
 
4322
        }
 
4323
 
 
4324
        len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
 
4325
 
 
4326
        SAFE_FREE(dbuf.dptr);
 
4327
 
 
4328
        return true;
 
4329
}
 
4330
 
 
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
****************************************************************************/
 
4337
 
 
4338
bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
 
4339
{
 
4340
        bool result = False;
 
4341
 
 
4342
        switch (level) {
 
4343
                case 2:
 
4344
                        result = set_driver_init_2(printer->info_2);
 
4345
                        break;
 
4346
 
 
4347
                default:
 
4348
                        DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
 
4349
                                level));
 
4350
                        break;
 
4351
        }
 
4352
 
 
4353
        return result;
 
4354
}
 
4355
 
 
4356
/****************************************************************************
 
4357
 Delete driver init data stored for a specified driver
 
4358
****************************************************************************/
 
4359
 
 
4360
bool del_driver_init(const char *drivername)
 
4361
{
 
4362
        char *key;
 
4363
        bool ret;
 
4364
 
 
4365
        if (!drivername || !*drivername) {
 
4366
                DEBUG(3,("del_driver_init: No drivername specified!\n"));
 
4367
                return false;
 
4368
        }
 
4369
 
 
4370
        if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
 
4371
                return false;
 
4372
        }
 
4373
 
 
4374
        DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
 
4375
                                drivername));
 
4376
 
 
4377
        ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
 
4378
        SAFE_FREE(key);
 
4379
        return ret;
 
4380
}
 
4381
 
 
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
****************************************************************************/
 
4389
 
 
4390
static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
 
4391
{
 
4392
        char *key = NULL;
 
4393
        uint8 *buf;
 
4394
        int buflen, len, ret;
 
4395
        int retlen;
 
4396
        TDB_DATA dbuf;
 
4397
 
 
4398
        buf = NULL;
 
4399
        buflen = 0;
 
4400
 
 
4401
 again:
 
4402
        len = 0;
 
4403
        len += pack_devicemode(info->devmode, buf+len, buflen-len);
 
4404
 
 
4405
        retlen = pack_values( info->data, buf+len, buflen-len );
 
4406
        if (retlen == -1) {
 
4407
                ret = -1;
 
4408
                goto done;
 
4409
        }
 
4410
        len += retlen;
 
4411
 
 
4412
        if (buflen < len) {
 
4413
                buf = (uint8 *)SMB_REALLOC(buf, len);
 
4414
                if (!buf) {
 
4415
                        DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
 
4416
                        ret = -1;
 
4417
                        goto done;
 
4418
                }
 
4419
                buflen = len;
 
4420
                goto again;
 
4421
        }
 
4422
 
 
4423
        SAFE_FREE(key);
 
4424
        if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
 
4425
                ret = (uint32)-1;
 
4426
                goto done;
 
4427
        }
 
4428
 
 
4429
        dbuf.dptr = buf;
 
4430
        dbuf.dsize = len;
 
4431
 
 
4432
        ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
 
4433
 
 
4434
done:
 
4435
        if (ret == -1)
 
4436
                DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
 
4437
 
 
4438
        SAFE_FREE(buf);
 
4439
 
 
4440
        DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
 
4441
                 info->sharename, info->drivername));
 
4442
 
 
4443
        return ret;
 
4444
}
 
4445
 
 
4446
/****************************************************************************
 
4447
 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
 
4448
****************************************************************************/
 
4449
 
 
4450
static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
 
4451
{
 
4452
        uint32 result;
 
4453
 
 
4454
        dump_a_printer(printer, level);
 
4455
 
 
4456
        switch (level) {
 
4457
                case 2:
 
4458
                        result = update_driver_init_2(printer->info_2);
 
4459
                        break;
 
4460
                default:
 
4461
                        result = 1;
 
4462
                        break;
 
4463
        }
 
4464
 
 
4465
        return result;
 
4466
}
 
4467
 
 
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
****************************************************************************/
 
4473
 
 
4474
static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
 
4475
                                const uint8_t *data, uint32_t data_len)
 
4476
{
 
4477
        struct spoolss_DeviceMode devmode;
 
4478
        enum ndr_err_code ndr_err;
 
4479
        DATA_BLOB blob;
 
4480
 
 
4481
        ZERO_STRUCT(devmode);
 
4482
 
 
4483
        blob = data_blob_const(data, data_len);
 
4484
 
 
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"));
 
4489
                return false;
 
4490
        }
 
4491
 
 
4492
        return convert_devicemode("", &devmode, &nt_devmode);
 
4493
}
 
4494
 
 
4495
/****************************************************************************
 
4496
 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
 
4497
 
 
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.
 
4502
 
 
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
 
4507
 have done on NT).
 
4508
 
 
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.
 
4511
 
 
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
****************************************************************************/
 
4516
 
 
4517
static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
 
4518
{
 
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;
 
4523
 
 
4524
        /*
 
4525
         * When the DEVMODE is already set on the printer, don't try to unpack it.
 
4526
         */
 
4527
        DEBUG(8,("save_driver_init_2: Enter...\n"));
 
4528
 
 
4529
        if ( !printer->info_2->devmode && data_len ) {
 
4530
                /*
 
4531
                 * Set devmode on printer info, so entire printer initialization can be
 
4532
                 * saved to tdb.
 
4533
                 */
 
4534
 
 
4535
                if ((ctx = talloc_init("save_driver_init_2")) == NULL)
 
4536
                        return WERR_NOMEM;
 
4537
 
 
4538
                if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
 
4539
                        status = WERR_NOMEM;
 
4540
                        goto done;
 
4541
                }
 
4542
 
 
4543
                ZERO_STRUCTP(nt_devmode);
 
4544
 
 
4545
                /*
 
4546
                 * The DEVMODE is held in the 'data' component of the param in raw binary.
 
4547
                 * Convert it to to a devmode structure
 
4548
                 */
 
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;
 
4552
                        goto done;
 
4553
                }
 
4554
 
 
4555
                printer->info_2->devmode = nt_devmode;
 
4556
        }
 
4557
 
 
4558
        /*
 
4559
         * Pack up and add (or update) the DEVMODE and any current printer data to
 
4560
         * a 'driver init' element in the tdb
 
4561
         *
 
4562
         */
 
4563
 
 
4564
        if ( update_driver_init(printer, 2) != 0 ) {
 
4565
                DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
 
4566
                status = WERR_NOMEM;
 
4567
                goto done;
 
4568
        }
 
4569
 
 
4570
        /*
 
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.
 
4574
         */
 
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));
 
4579
        }
 
4580
 
 
4581
  done:
 
4582
        talloc_destroy(ctx);
 
4583
        free_nt_devicemode( &nt_devmode );
 
4584
 
 
4585
        printer->info_2->devmode = tmp_devmode;
 
4586
 
 
4587
        return status;
 
4588
}
 
4589
 
 
4590
/****************************************************************************
 
4591
 Update the driver init info (DEVMODE and specifics) for a printer
 
4592
****************************************************************************/
 
4593
 
 
4594
WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
 
4595
{
 
4596
        WERROR status = WERR_OK;
 
4597
 
 
4598
        switch (level) {
 
4599
                case 2:
 
4600
                        status = save_driver_init_2( printer, data, data_len );
 
4601
                        break;
 
4602
                default:
 
4603
                        status = WERR_UNKNOWN_LEVEL;
 
4604
                        break;
 
4605
        }
 
4606
 
 
4607
        return status;
 
4608
}
 
4609
 
 
4610
/****************************************************************************
 
4611
 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
 
4612
 
 
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.
 
4620
                                                    --jerry
 
4621
 
 
4622
****************************************************************************/
 
4623
 
 
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)
 
4626
{
 
4627
        WERROR result;
 
4628
        fstring servername;
 
4629
 
 
4630
        DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
 
4631
 
 
4632
        if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
 
4633
                DEBUG(0,("get_a_printer: talloc() fail.\n"));
 
4634
                return WERR_NOMEM;
 
4635
        }
 
4636
 
 
4637
        switch (level) {
 
4638
                case 2:
 
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 );
 
4642
                                return WERR_NOMEM;
 
4643
                        }
 
4644
 
 
4645
                        if ( print_hnd )
 
4646
                                fstrcpy( servername, print_hnd->servername );
 
4647
                        else {
 
4648
                                fstrcpy( servername, "%L" );
 
4649
                                standard_sub_basic( "", "", servername,
 
4650
                                                    sizeof(servername)-1 );
 
4651
                        }
 
4652
 
 
4653
                        result = get_a_printer_2( (*pp_printer)->info_2,
 
4654
                                        servername, sharename, get_loc_com);
 
4655
 
 
4656
                        /* we have a new printer now.  Save it with this handle */
 
4657
 
 
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)));
 
4662
                                return result;
 
4663
                        }
 
4664
 
 
4665
                        dump_a_printer( *pp_printer, level);
 
4666
 
 
4667
                        break;
 
4668
 
 
4669
                default:
 
4670
                        TALLOC_FREE( *pp_printer );
 
4671
                        return WERR_UNKNOWN_LEVEL;
 
4672
        }
 
4673
 
 
4674
        return WERR_OK;
 
4675
}
 
4676
 
 
4677
WERROR get_a_printer( Printer_entry *print_hnd,
 
4678
                        NT_PRINTER_INFO_LEVEL **pp_printer,
 
4679
                        uint32 level,
 
4680
                        const char *sharename)
 
4681
{
 
4682
        return get_a_printer_internal(print_hnd, pp_printer, level,
 
4683
                                        sharename, true);
 
4684
}
 
4685
 
 
4686
WERROR get_a_printer_search( Printer_entry *print_hnd,
 
4687
                        NT_PRINTER_INFO_LEVEL **pp_printer,
 
4688
                        uint32 level,
 
4689
                        const char *sharename)
 
4690
{
 
4691
        return get_a_printer_internal(print_hnd, pp_printer, level,
 
4692
                                        sharename, false);
 
4693
}
 
4694
 
 
4695
/****************************************************************************
 
4696
 Deletes a NT_PRINTER_INFO_LEVEL struct.
 
4697
****************************************************************************/
 
4698
 
 
4699
uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
 
4700
{
 
4701
        NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
 
4702
 
 
4703
        if ( !printer )
 
4704
                return 0;
 
4705
 
 
4706
        switch (level) {
 
4707
                case 2:
 
4708
                        if ( printer->info_2 )
 
4709
                                free_nt_printer_info_level_2(&printer->info_2);
 
4710
                        break;
 
4711
 
 
4712
                default:
 
4713
                        DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
 
4714
                        return 1;
 
4715
        }
 
4716
 
 
4717
        TALLOC_FREE(*pp_printer);
 
4718
 
 
4719
        return 0;
 
4720
}
 
4721
 
 
4722
/****************************************************************************
 
4723
****************************************************************************/
 
4724
uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
 
4725
{
 
4726
        uint32 result;
 
4727
        DEBUG(104,("adding a printer at level [%d]\n", level));
 
4728
        dump_a_printer_driver(driver, level);
 
4729
 
 
4730
        switch (level) {
 
4731
                case 3:
 
4732
                        result=add_a_printer_driver_3(driver.info_3);
 
4733
                        break;
 
4734
 
 
4735
                case 6:
 
4736
                        result=add_a_printer_driver_6(driver.info_6);
 
4737
                        break;
 
4738
 
 
4739
                default:
 
4740
                        result=1;
 
4741
                        break;
 
4742
        }
 
4743
 
 
4744
        return result;
 
4745
}
 
4746
/****************************************************************************
 
4747
****************************************************************************/
 
4748
 
 
4749
WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
 
4750
                            const char *drivername, const char *architecture,
 
4751
                            uint32_t version)
 
4752
{
 
4753
        WERROR result;
 
4754
 
 
4755
        switch (level) {
 
4756
                case 3:
 
4757
                        /* Sometime we just want any version of the driver */
 
4758
 
 
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,
 
4762
                                                architecture, 3);
 
4763
 
 
4764
                                if ( !W_ERROR_IS_OK(result) ) {
 
4765
                                        result = get_a_printer_driver_3( &driver->info_3,
 
4766
                                                        drivername, architecture, 2 );
 
4767
                                }
 
4768
                        } else {
 
4769
                                result = get_a_printer_driver_3(&driver->info_3, drivername,
 
4770
                                        architecture, version);
 
4771
                        }
 
4772
                        break;
 
4773
 
 
4774
                default:
 
4775
                        result=W_ERROR(1);
 
4776
                        break;
 
4777
        }
 
4778
 
 
4779
        if (W_ERROR_IS_OK(result))
 
4780
                dump_a_printer_driver(*driver, level);
 
4781
 
 
4782
        return result;
 
4783
}
 
4784
 
 
4785
/****************************************************************************
 
4786
****************************************************************************/
 
4787
uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
 
4788
{
 
4789
        uint32 result;
 
4790
 
 
4791
        switch (level) {
 
4792
                case 3:
 
4793
                {
 
4794
                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
 
4795
                        if (driver.info_3 != NULL)
 
4796
                        {
 
4797
                                info3=driver.info_3;
 
4798
                                SAFE_FREE(info3->dependentfiles);
 
4799
                                ZERO_STRUCTP(info3);
 
4800
                                SAFE_FREE(info3);
 
4801
                                result=0;
 
4802
                        } else {
 
4803
                                result=4;
 
4804
                        }
 
4805
                        break;
 
4806
                }
 
4807
                case 6:
 
4808
                {
 
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);
 
4815
                                SAFE_FREE(info6);
 
4816
                                result=0;
 
4817
                        } else {
 
4818
                                result=4;
 
4819
                        }
 
4820
                        break;
 
4821
                }
 
4822
                default:
 
4823
                        result=1;
 
4824
                        break;
 
4825
        }
 
4826
        return result;
 
4827
}
 
4828
 
 
4829
 
 
4830
/****************************************************************************
 
4831
  Determine whether or not a particular driver is currently assigned
 
4832
  to a printer
 
4833
****************************************************************************/
 
4834
 
 
4835
bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
 
4836
{
 
4837
        int snum;
 
4838
        int n_services = lp_numservices();
 
4839
        NT_PRINTER_INFO_LEVEL *printer = NULL;
 
4840
        bool in_use = False;
 
4841
 
 
4842
        if ( !info_3 )
 
4843
                return False;
 
4844
 
 
4845
        DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
 
4846
 
 
4847
        /* loop through the printers.tdb and check for the drivername */
 
4848
 
 
4849
        for (snum=0; snum<n_services && !in_use; snum++) {
 
4850
                if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
 
4851
                        continue;
 
4852
 
 
4853
                if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
 
4854
                        continue;
 
4855
 
 
4856
                if ( strequal(info_3->name, printer->info_2->drivername) )
 
4857
                        in_use = True;
 
4858
 
 
4859
                free_a_printer( &printer, 2 );
 
4860
        }
 
4861
 
 
4862
        DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
 
4863
 
 
4864
        if ( in_use ) {
 
4865
                NT_PRINTER_DRIVER_INFO_LEVEL d;
 
4866
                WERROR werr;
 
4867
 
 
4868
                DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
 
4869
 
 
4870
                /* we can still remove the driver if there is one of
 
4871
                   "Windows NT x86" version 2 or 3 left */
 
4872
 
 
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 );
 
4875
                }
 
4876
                else {
 
4877
                        switch ( info_3->cversion ) {
 
4878
                        case 2:
 
4879
                                werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
 
4880
                                break;
 
4881
                        case 3:
 
4882
                                werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
 
4883
                                break;
 
4884
                        default:
 
4885
                                DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
 
4886
                                        info_3->cversion));
 
4887
                                werr = WERR_UNKNOWN_PRINTER_DRIVER;
 
4888
                                break;
 
4889
                        }
 
4890
                }
 
4891
 
 
4892
                /* now check the error code */
 
4893
 
 
4894
                if ( W_ERROR_IS_OK(werr) ) {
 
4895
                        /* it's ok to remove the driver, we have other architctures left */
 
4896
                        in_use = False;
 
4897
                        free_a_printer_driver( d, 3 );
 
4898
                }
 
4899
        }
 
4900
 
 
4901
        /* report that the driver is not in use by default */
 
4902
 
 
4903
        return in_use;
 
4904
}
 
4905
 
 
4906
 
 
4907
/**********************************************************************
 
4908
 Check to see if a ogiven file is in use by *info
 
4909
 *********************************************************************/
 
4910
 
 
4911
static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
 
4912
{
 
4913
        int i = 0;
 
4914
 
 
4915
        if ( !info )
 
4916
                return False;
 
4917
 
 
4918
        /* mz: skip files that are in the list but already deleted */
 
4919
        if (!file || !file[0]) {
 
4920
                return false;
 
4921
        }
 
4922
 
 
4923
        if ( strequal(file, info->driverpath) )
 
4924
                return True;
 
4925
 
 
4926
        if ( strequal(file, info->datafile) )
 
4927
                return True;
 
4928
 
 
4929
        if ( strequal(file, info->configfile) )
 
4930
                return True;
 
4931
 
 
4932
        if ( strequal(file, info->helpfile) )
 
4933
                return True;
 
4934
 
 
4935
        /* see of there are any dependent files to examine */
 
4936
 
 
4937
        if ( !info->dependentfiles )
 
4938
                return False;
 
4939
 
 
4940
        while ( *info->dependentfiles[i] ) {
 
4941
                if ( strequal(file, info->dependentfiles[i]) )
 
4942
                        return True;
 
4943
                i++;
 
4944
        }
 
4945
 
 
4946
        return False;
 
4947
 
 
4948
}
 
4949
 
 
4950
/**********************************************************************
 
4951
 Utility function to remove the dependent file pointed to by the
 
4952
 input parameter from the list
 
4953
 *********************************************************************/
 
4954
 
 
4955
static void trim_dependent_file( fstring files[], int idx )
 
4956
{
 
4957
 
 
4958
        /* bump everything down a slot */
 
4959
 
 
4960
        while( *files[idx+1] ) {
 
4961
                fstrcpy( files[idx], files[idx+1] );
 
4962
                idx++;
 
4963
        }
 
4964
 
 
4965
        *files[idx] = '\0';
 
4966
 
 
4967
        return;
 
4968
}
 
4969
 
 
4970
/**********************************************************************
 
4971
 Check if any of the files used by src are also used by drv
 
4972
 *********************************************************************/
 
4973
 
 
4974
static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
 
4975
                                       NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
 
4976
{
 
4977
        bool    in_use = False;
 
4978
        int     i = 0;
 
4979
 
 
4980
        if ( !src || !drv )
 
4981
                return False;
 
4982
 
 
4983
        /* check each file.  Remove it from the src structure if it overlaps */
 
4984
 
 
4985
        if ( drv_file_in_use(src->driverpath, drv) ) {
 
4986
                in_use = True;
 
4987
                DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
 
4988
                fstrcpy( src->driverpath, "" );
 
4989
        }
 
4990
 
 
4991
        if ( drv_file_in_use(src->datafile, drv) ) {
 
4992
                in_use = True;
 
4993
                DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
 
4994
                fstrcpy( src->datafile, "" );
 
4995
        }
 
4996
 
 
4997
        if ( drv_file_in_use(src->configfile, drv) ) {
 
4998
                in_use = True;
 
4999
                DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
 
5000
                fstrcpy( src->configfile, "" );
 
5001
        }
 
5002
 
 
5003
        if ( drv_file_in_use(src->helpfile, drv) ) {
 
5004
                in_use = True;
 
5005
                DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
 
5006
                fstrcpy( src->helpfile, "" );
 
5007
        }
 
5008
 
 
5009
        /* are there any dependentfiles to examine? */
 
5010
 
 
5011
        if ( !src->dependentfiles )
 
5012
                return in_use;
 
5013
 
 
5014
        while ( *src->dependentfiles[i] ) {
 
5015
                if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
 
5016
                        in_use = True;
 
5017
                        DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
 
5018
                        trim_dependent_file( src->dependentfiles, i );
 
5019
                } else
 
5020
                        i++;
 
5021
        }
 
5022
 
 
5023
        return in_use;
 
5024
}
 
5025
 
 
5026
/****************************************************************************
 
5027
  Determine whether or not a particular driver files are currently being
 
5028
  used by any other driver.
 
5029
 
 
5030
  Return value is True if any files were in use by other drivers
 
5031
  and False otherwise.
 
5032
 
 
5033
  Upon return, *info has been modified to only contain the driver files
 
5034
  which are not in use
 
5035
 
 
5036
  Fix from mz:
 
5037
 
 
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
 
5040
  match.
 
5041
****************************************************************************/
 
5042
 
 
5043
bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
 
5044
{
 
5045
        int                             i;
 
5046
        int                             ndrivers;
 
5047
        uint32                          version;
 
5048
        fstring                         *list = NULL;
 
5049
        NT_PRINTER_DRIVER_INFO_LEVEL    driver;
 
5050
        bool in_use = false;
 
5051
 
 
5052
        if ( !info )
 
5053
                return False;
 
5054
 
 
5055
        version = info->cversion;
 
5056
 
 
5057
        /* loop over all driver versions */
 
5058
 
 
5059
        DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
 
5060
 
 
5061
        /* get the list of drivers */
 
5062
 
 
5063
        list = NULL;
 
5064
        ndrivers = get_ntdrivers(&list, info->environment, version);
 
5065
 
 
5066
        DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
 
5067
                ndrivers, info->environment, version));
 
5068
 
 
5069
        /* check each driver for overlap in files */
 
5070
 
 
5071
        for (i=0; i<ndrivers; i++) {
 
5072
                DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
 
5073
 
 
5074
                ZERO_STRUCT(driver);
 
5075
 
 
5076
                if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
 
5077
                        SAFE_FREE(list);
 
5078
                        return True;
 
5079
                }
 
5080
 
 
5081
                /* check if d2 uses any files from d1 */
 
5082
                /* only if this is a different driver than the one being deleted */
 
5083
 
 
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. */
 
5089
                                in_use = true;
 
5090
                        }
 
5091
                }
 
5092
 
 
5093
                free_a_printer_driver(driver, 3);
 
5094
        }
 
5095
 
 
5096
        SAFE_FREE(list);
 
5097
 
 
5098
        DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
 
5099
 
 
5100
        driver.info_3 = info;
 
5101
 
 
5102
        if ( DEBUGLEVEL >= 20 )
 
5103
                dump_a_printer_driver( driver, 3 );
 
5104
 
 
5105
        return in_use;
 
5106
}
 
5107
 
 
5108
/****************************************************************************
 
5109
  Actually delete the driver files.  Make sure that
 
5110
  printer_driver_files_in_use() return False before calling
 
5111
  this.
 
5112
****************************************************************************/
 
5113
 
 
5114
static bool delete_driver_files(struct pipes_struct *rpc_pipe,
 
5115
                                NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
 
5116
{
 
5117
        int i = 0;
 
5118
        char *s;
 
5119
        const char *file;
 
5120
        connection_struct *conn;
 
5121
        NTSTATUS nt_status;
 
5122
        SMB_STRUCT_STAT  st;
 
5123
        char *oldcwd;
 
5124
        fstring printdollar;
 
5125
        int printdollar_snum;
 
5126
        bool ret = false;
 
5127
 
 
5128
        if ( !info_3 )
 
5129
                return False;
 
5130
 
 
5131
        DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
 
5132
 
 
5133
        fstrcpy(printdollar, "print$");
 
5134
 
 
5135
        printdollar_snum = find_service(printdollar);
 
5136
        if (printdollar_snum == -1) {
 
5137
                return false;
 
5138
        }
 
5139
 
 
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)));
 
5146
                return false;
 
5147
        }
 
5148
 
 
5149
        if ( !CAN_WRITE(conn) ) {
 
5150
                DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
 
5151
                goto fail;
 
5152
        }
 
5153
 
 
5154
        /* now delete the files; must strip the '\print$' string from
 
5155
           fron of path                                                */
 
5156
 
 
5157
        if ( *info_3->driverpath ) {
 
5158
                if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
 
5159
                        file = s;
 
5160
                        driver_unix_convert(conn,file,&st);
 
5161
                        DEBUG(10,("deleting driverfile [%s]\n", s));
 
5162
                        unlink_internals(conn, NULL, 0, file, False);
 
5163
                }
 
5164
        }
 
5165
 
 
5166
        if ( *info_3->configfile ) {
 
5167
                if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
 
5168
                        file = s;
 
5169
                        driver_unix_convert(conn,file,&st);
 
5170
                        DEBUG(10,("deleting configfile [%s]\n", s));
 
5171
                        unlink_internals(conn, NULL, 0, file, False);
 
5172
                }
 
5173
        }
 
5174
 
 
5175
        if ( *info_3->datafile ) {
 
5176
                if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
 
5177
                        file = s;
 
5178
                        driver_unix_convert(conn,file,&st);
 
5179
                        DEBUG(10,("deleting datafile [%s]\n", s));
 
5180
                        unlink_internals(conn, NULL, 0, file, False);
 
5181
                }
 
5182
        }
 
5183
 
 
5184
        if ( *info_3->helpfile ) {
 
5185
                if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
 
5186
                        file = s;
 
5187
                        driver_unix_convert(conn,file,&st);
 
5188
                        DEBUG(10,("deleting helpfile [%s]\n", s));
 
5189
                        unlink_internals(conn, NULL, 0, file, False);
 
5190
                }
 
5191
        }
 
5192
 
 
5193
        /* check if we are done removing files */
 
5194
 
 
5195
        if ( info_3->dependentfiles ) {
 
5196
                while ( info_3->dependentfiles[i][0] ) {
 
5197
                        char *p;
 
5198
 
 
5199
                        /* bypass the "\print$" portion of the path */
 
5200
 
 
5201
                        if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
 
5202
                                file = p;
 
5203
                                driver_unix_convert(conn,file,&st);
 
5204
                                DEBUG(10,("deleting dependent file [%s]\n", file));
 
5205
                                unlink_internals(conn, NULL, 0, file, False);
 
5206
                        }
 
5207
 
 
5208
                        i++;
 
5209
                }
 
5210
        }
 
5211
 
 
5212
        goto done;
 
5213
 fail:
 
5214
        ret = false;
 
5215
 done:
 
5216
        if (conn != NULL) {
 
5217
                vfs_ChDir(conn, oldcwd);
 
5218
                conn_free_internal(conn);
 
5219
        }
 
5220
        return ret;
 
5221
}
 
5222
 
 
5223
/****************************************************************************
 
5224
 Remove a printer driver from the TDB.  This assumes that the the driver was
 
5225
 previously looked up.
 
5226
 ***************************************************************************/
 
5227
 
 
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 )
 
5231
{
 
5232
        char *key = NULL;
 
5233
        const char     *arch;
 
5234
        TDB_DATA        dbuf;
 
5235
        NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
 
5236
 
 
5237
        /* delete the tdb data first */
 
5238
 
 
5239
        arch = get_short_archi(info_3->environment);
 
5240
        if (!arch) {
 
5241
                return WERR_UNKNOWN_PRINTER_DRIVER;
 
5242
        }
 
5243
        if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
 
5244
                        arch, version, info_3->name) < 0) {
 
5245
                return WERR_NOMEM;
 
5246
        }
 
5247
 
 
5248
        DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
 
5249
                key, delete_files ? "TRUE" : "FALSE" ));
 
5250
 
 
5251
        ctr.info_3 = info_3;
 
5252
        dump_a_printer_driver( ctr, 3 );
 
5253
 
 
5254
        /* check if the driver actually exists for this environment */
 
5255
 
 
5256
        dbuf = tdb_fetch_bystring( tdb_drivers, key );
 
5257
        if ( !dbuf.dptr ) {
 
5258
                DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
 
5259
                SAFE_FREE(key);
 
5260
                return WERR_UNKNOWN_PRINTER_DRIVER;
 
5261
        }
 
5262
 
 
5263
        SAFE_FREE( dbuf.dptr );
 
5264
 
 
5265
        /* ok... the driver exists so the delete should return success */
 
5266
 
 
5267
        if (tdb_delete_bystring(tdb_drivers, key) == -1) {
 
5268
                DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
 
5269
                SAFE_FREE(key);
 
5270
                return WERR_ACCESS_DENIED;
 
5271
        }
 
5272
 
 
5273
        /*
 
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
 
5277
         */
 
5278
 
 
5279
        if ( delete_files )
 
5280
                delete_driver_files(rpc_pipe, info_3);
 
5281
 
 
5282
        DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
 
5283
        SAFE_FREE(key);
 
5284
 
 
5285
        return WERR_OK;
 
5286
}
 
5287
 
 
5288
/****************************************************************************
 
5289
 Store a security desc for a printer.
 
5290
****************************************************************************/
 
5291
 
 
5292
WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
 
5293
{
 
5294
        SEC_DESC_BUF *new_secdesc_ctr = NULL;
 
5295
        SEC_DESC_BUF *old_secdesc_ctr = NULL;
 
5296
        TALLOC_CTX *mem_ctx = NULL;
 
5297
        TDB_DATA kbuf;
 
5298
        TDB_DATA dbuf;
 
5299
        DATA_BLOB blob;
 
5300
        WERROR status;
 
5301
        NTSTATUS nt_status;
 
5302
 
 
5303
        mem_ctx = talloc_init("nt_printing_setsec");
 
5304
        if (mem_ctx == NULL)
 
5305
                return WERR_NOMEM;
 
5306
 
 
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. */
 
5311
 
 
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;
 
5316
                size_t size;
 
5317
 
 
5318
                if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
 
5319
                        status = WERR_NOMEM;
 
5320
                        goto out;
 
5321
                }
 
5322
 
 
5323
                /* Pick out correct owner and group sids */
 
5324
 
 
5325
                owner_sid = secdesc_ctr->sd->owner_sid ?
 
5326
                        secdesc_ctr->sd->owner_sid :
 
5327
                        old_secdesc_ctr->sd->owner_sid;
 
5328
 
 
5329
                group_sid = secdesc_ctr->sd->group_sid ?
 
5330
                        secdesc_ctr->sd->group_sid :
 
5331
                        old_secdesc_ctr->sd->group_sid;
 
5332
 
 
5333
                dacl = secdesc_ctr->sd->dacl ?
 
5334
                        secdesc_ctr->sd->dacl :
 
5335
                        old_secdesc_ctr->sd->dacl;
 
5336
 
 
5337
                sacl = secdesc_ctr->sd->sacl ?
 
5338
                        secdesc_ctr->sd->sacl :
 
5339
                        old_secdesc_ctr->sd->sacl;
 
5340
 
 
5341
                /* Make a deep copy of the security descriptor */
 
5342
 
 
5343
                psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
 
5344
                                    owner_sid, group_sid,
 
5345
                                    sacl,
 
5346
                                    dacl,
 
5347
                                    &size);
 
5348
 
 
5349
                if (!psd) {
 
5350
                        status = WERR_NOMEM;
 
5351
                        goto out;
 
5352
                }
 
5353
 
 
5354
                new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
 
5355
        }
 
5356
 
 
5357
        if (!new_secdesc_ctr) {
 
5358
                new_secdesc_ctr = secdesc_ctr;
 
5359
        }
 
5360
 
 
5361
        /* Store the security descriptor in a tdb */
 
5362
 
 
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);
 
5367
                goto out;
 
5368
        }
 
5369
 
 
5370
        kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
 
5371
 
 
5372
        dbuf.dptr = (unsigned char *)blob.data;
 
5373
        dbuf.dsize = blob.length;
 
5374
 
 
5375
        if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
 
5376
                status = WERR_OK;
 
5377
        } else {
 
5378
                DEBUG(1,("Failed to store secdesc for %s\n", sharename));
 
5379
                status = WERR_BADFUNC;
 
5380
        }
 
5381
 
 
5382
        /* Free malloc'ed memory */
 
5383
        talloc_free(blob.data);
 
5384
 
 
5385
 out:
 
5386
 
 
5387
        if (mem_ctx)
 
5388
                talloc_destroy(mem_ctx);
 
5389
        return status;
 
5390
}
 
5391
 
 
5392
/****************************************************************************
 
5393
 Construct a default security descriptor buffer for a printer.
 
5394
****************************************************************************/
 
5395
 
 
5396
static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
 
5397
{
 
5398
        SEC_ACE ace[5]; /* max number of ace entries */
 
5399
        int i = 0;
 
5400
        uint32_t sa;
 
5401
        SEC_ACL *psa = NULL;
 
5402
        SEC_DESC_BUF *sdb = NULL;
 
5403
        SEC_DESC *psd = NULL;
 
5404
        DOM_SID adm_sid;
 
5405
        size_t sd_size;
 
5406
 
 
5407
        /* Create an ACE where Everyone is allowed to print */
 
5408
 
 
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);
 
5412
 
 
5413
        /* Add the domain admins group if we are a DC */
 
5414
 
 
5415
        if ( IS_DC ) {
 
5416
                DOM_SID domadmins_sid;
 
5417
 
 
5418
                sid_copy(&domadmins_sid, get_global_sam_sid());
 
5419
                sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
 
5420
 
 
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);
 
5427
        }
 
5428
        else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
 
5429
                sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
 
5430
 
 
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);
 
5437
        }
 
5438
 
 
5439
        /* add BUILTIN\Administrators as FULL CONTROL */
 
5440
 
 
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);
 
5448
 
 
5449
        /* Make the security descriptor owned by the BUILTIN\Administrators */
 
5450
 
 
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
 
5454
           NT5 machine. */
 
5455
 
 
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);
 
5461
        }
 
5462
 
 
5463
        if (!psd) {
 
5464
                DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
 
5465
                return NULL;
 
5466
        }
 
5467
 
 
5468
        sdb = make_sec_desc_buf(ctx, sd_size, psd);
 
5469
 
 
5470
        DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
 
5471
                 (unsigned int)sd_size));
 
5472
 
 
5473
        return sdb;
 
5474
}
 
5475
 
 
5476
/****************************************************************************
 
5477
 Get a security desc for a printer.
 
5478
****************************************************************************/
 
5479
 
 
5480
bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
 
5481
{
 
5482
        TDB_DATA kbuf;
 
5483
        TDB_DATA dbuf;
 
5484
        DATA_BLOB blob;
 
5485
        char *temp;
 
5486
        NTSTATUS status;
 
5487
 
 
5488
        if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
 
5489
                sharename = temp + 1;
 
5490
        }
 
5491
 
 
5492
        /* Fetch security descriptor from tdb */
 
5493
 
 
5494
        kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
 
5495
 
 
5496
        dbuf = tdb_fetch(tdb_printers, kbuf);
 
5497
        if (dbuf.dptr) {
 
5498
 
 
5499
                status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
 
5500
                                                 secdesc_ctr);
 
5501
                SAFE_FREE(dbuf.dptr);
 
5502
 
 
5503
                if (NT_STATUS_IS_OK(status)) {
 
5504
                        return true;
 
5505
                }
 
5506
        }
 
5507
 
 
5508
        *secdesc_ctr = construct_default_printer_sdb(ctx);
 
5509
        if (!*secdesc_ctr) {
 
5510
                return false;
 
5511
        }
 
5512
 
 
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);
 
5520
        }
 
5521
 
 
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. */
 
5525
 
 
5526
        if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
 
5527
                DOM_SID owner_sid;
 
5528
 
 
5529
                /* Change sd owner to workgroup administrator */
 
5530
 
 
5531
                if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
 
5532
                        SEC_DESC_BUF *new_secdesc_ctr = NULL;
 
5533
                        SEC_DESC *psd = NULL;
 
5534
                        size_t size;
 
5535
 
 
5536
                        /* Create new sd */
 
5537
 
 
5538
                        sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
 
5539
 
 
5540
                        psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
 
5541
                                            &owner_sid,
 
5542
                                            (*secdesc_ctr)->sd->group_sid,
 
5543
                                            (*secdesc_ctr)->sd->sacl,
 
5544
                                            (*secdesc_ctr)->sd->dacl,
 
5545
                                            &size);
 
5546
 
 
5547
                        if (!psd) {
 
5548
                                return False;
 
5549
                        }
 
5550
 
 
5551
                        new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
 
5552
                        if (!new_secdesc_ctr) {
 
5553
                                return False;
 
5554
                        }
 
5555
 
 
5556
                        /* Swap with other one */
 
5557
 
 
5558
                        *secdesc_ctr = new_secdesc_ctr;
 
5559
 
 
5560
                        /* Set it */
 
5561
 
 
5562
                        nt_printing_setsec(sharename, *secdesc_ctr);
 
5563
                }
 
5564
        }
 
5565
 
 
5566
        if (DEBUGLEVEL >= 10) {
 
5567
                SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
 
5568
                int i;
 
5569
 
 
5570
                DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
 
5571
                           sharename, the_acl->num_aces));
 
5572
 
 
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));
 
5578
                }
 
5579
        }
 
5580
 
 
5581
        return True;
 
5582
}
 
5583
 
 
5584
/* error code:
 
5585
        0: everything OK
 
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
 
5591
*/
 
5592
 
 
5593
/*
 
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 !
 
5597
 
 
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 :-).
 
5602
 
 
5603
        If the /usr/local/samba/lib directory (default dir), you will have
 
5604
        5 files to describe all of this.
 
5605
 
 
5606
        3 files for the printers (1 by printer):
 
5607
                NTprinter_laser A
 
5608
                NTprinter_laser B
 
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
 
5613
 
 
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 :-)
 
5617
 
 
5618
*/
 
5619
 
 
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. */
 
5623
 
 
5624
void map_printer_permissions(SEC_DESC *sd)
 
5625
{
 
5626
        int i;
 
5627
 
 
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);
 
5631
        }
 
5632
}
 
5633
 
 
5634
void map_job_permissions(SEC_DESC *sd)
 
5635
{
 
5636
        int i;
 
5637
 
 
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);
 
5641
        }
 
5642
}
 
5643
 
 
5644
 
 
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.
 
5649
 
 
5650
   PRINTER_ACCESS_ADMINISTER:
 
5651
       print_queue_pause, print_queue_resume, update_printer_sec,
 
5652
       update_printer, spoolss_addprinterex_level_2,
 
5653
       _spoolss_setprinterdata
 
5654
 
 
5655
   PRINTER_ACCESS_USE:
 
5656
       print_job_start
 
5657
 
 
5658
   JOB_ACCESS_ADMINISTER:
 
5659
       print_job_delete, print_job_pause, print_job_resume,
 
5660
       print_queue_purge
 
5661
 
 
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)
 
5666
 
 
5667
 ****************************************************************************/
 
5668
bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
 
5669
                        int access_type)
 
5670
{
 
5671
        SEC_DESC_BUF *secdesc = NULL;
 
5672
        uint32 access_granted;
 
5673
        NTSTATUS status;
 
5674
        const char *pname;
 
5675
        TALLOC_CTX *mem_ctx = NULL;
 
5676
        SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
5677
 
 
5678
        /* If user is NULL then use the current_user structure */
 
5679
 
 
5680
        /* Always allow root or SE_PRINT_OPERATROR to do anything */
 
5681
 
 
5682
        if (server_info->utok.uid == sec_initial_uid()
 
5683
            || user_has_privileges(server_info->ptok, &se_printop ) ) {
 
5684
                return True;
 
5685
        }
 
5686
 
 
5687
        /* Get printer name */
 
5688
 
 
5689
        pname = PRINTERNAME(snum);
 
5690
 
 
5691
        if (!pname || !*pname) {
 
5692
                errno = EACCES;
 
5693
                return False;
 
5694
        }
 
5695
 
 
5696
        /* Get printer security descriptor */
 
5697
 
 
5698
        if(!(mem_ctx = talloc_init("print_access_check"))) {
 
5699
                errno = ENOMEM;
 
5700
                return False;
 
5701
        }
 
5702
 
 
5703
        if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
 
5704
                talloc_destroy(mem_ctx);
 
5705
                errno = ENOMEM;
 
5706
                return False;
 
5707
        }
 
5708
 
 
5709
        if (access_type == JOB_ACCESS_ADMINISTER) {
 
5710
                SEC_DESC_BUF *parent_secdesc = secdesc;
 
5711
 
 
5712
                /* Create a child security descriptor to check permissions
 
5713
                   against.  This is because print jobs are child objects
 
5714
                   objects of a printer. */
 
5715
 
 
5716
                status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
 
5717
 
 
5718
                if (!NT_STATUS_IS_OK(status)) {
 
5719
                        talloc_destroy(mem_ctx);
 
5720
                        errno = map_errno_from_nt_status(status);
 
5721
                        return False;
 
5722
                }
 
5723
 
 
5724
                map_job_permissions(secdesc->sd);
 
5725
        } else {
 
5726
                map_printer_permissions(secdesc->sd);
 
5727
        }
 
5728
 
 
5729
        /* Check access */
 
5730
        status = se_access_check(secdesc->sd, server_info->ptok, access_type,
 
5731
                                 &access_granted);
 
5732
 
 
5733
        DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
 
5734
 
 
5735
        /* see if we need to try the printer admin list */
 
5736
 
 
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);
 
5742
                return True;
 
5743
        }
 
5744
 
 
5745
        talloc_destroy(mem_ctx);
 
5746
 
 
5747
        if (!NT_STATUS_IS_OK(status)) {
 
5748
                errno = EACCES;
 
5749
        }
 
5750
 
 
5751
        return NT_STATUS_IS_OK(status);
 
5752
}
 
5753
 
 
5754
/****************************************************************************
 
5755
 Check the time parameters allow a print operation.
 
5756
*****************************************************************************/
 
5757
 
 
5758
bool print_time_access_check(const char *servicename)
 
5759
{
 
5760
        NT_PRINTER_INFO_LEVEL *printer = NULL;
 
5761
        bool ok = False;
 
5762
        time_t now = time(NULL);
 
5763
        struct tm *t;
 
5764
        uint32 mins;
 
5765
 
 
5766
        if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
 
5767
                return False;
 
5768
 
 
5769
        if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
 
5770
                ok = True;
 
5771
 
 
5772
        t = gmtime(&now);
 
5773
        mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
 
5774
 
 
5775
        if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
 
5776
                ok = True;
 
5777
 
 
5778
        free_a_printer(&printer, 2);
 
5779
 
 
5780
        if (!ok)
 
5781
                errno = EACCES;
 
5782
 
 
5783
        return ok;
 
5784
}
 
5785
 
 
5786
/****************************************************************************
 
5787
 Fill in the servername sent in the _spoolss_open_printer_ex() call
 
5788
****************************************************************************/
 
5789
 
 
5790
char* get_server_name( Printer_entry *printer )
 
5791
{
 
5792
        return printer->servername;
 
5793
}
 
5794
 
 
5795