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 | struct table_node {
|
---|
208 | const char *long_archi;
|
---|
209 | const char *short_archi;
|
---|
210 | int version;
|
---|
211 | };
|
---|
212 |
|
---|
213 | #define SPL_ARCH_WIN40 "WIN40"
|
---|
214 | #define SPL_ARCH_W32X86 "W32X86"
|
---|
215 | #define SPL_ARCH_W32MIPS "W32MIPS"
|
---|
216 | #define SPL_ARCH_W32ALPHA "W32ALPHA"
|
---|
217 | #define SPL_ARCH_W32PPC "W32PPC"
|
---|
218 | #define SPL_ARCH_IA64 "IA64"
|
---|
219 | #define SPL_ARCH_X64 "x64"
|
---|
220 |
|
---|
221 | static const struct table_node archi_table[]= {
|
---|
222 |
|
---|
223 | {"Windows 4.0", SPL_ARCH_WIN40, 0 },
|
---|
224 | {"Windows NT x86", SPL_ARCH_W32X86, 2 },
|
---|
225 | {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
|
---|
226 | {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
|
---|
227 | {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
|
---|
228 | {"Windows IA64", SPL_ARCH_IA64, 3 },
|
---|
229 | {"Windows x64", SPL_ARCH_X64, 3 },
|
---|
230 | {NULL, "", -1 }
|
---|
231 | };
|
---|
232 |
|
---|
233 |
|
---|
234 | /****************************************************************************
|
---|
235 | generate a new TDB_DATA key for storing a printer
|
---|
236 | ****************************************************************************/
|
---|
237 |
|
---|
238 | static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
|
---|
239 | {
|
---|
240 | fstring share;
|
---|
241 | char *keystr = NULL;
|
---|
242 | TDB_DATA key;
|
---|
243 |
|
---|
244 | fstrcpy(share, sharename);
|
---|
245 | strlower_m(share);
|
---|
246 |
|
---|
247 | keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
|
---|
248 | key = string_term_tdb_data(keystr ? keystr : "");
|
---|
249 |
|
---|
250 | return key;
|
---|
251 | }
|
---|
252 |
|
---|
253 | /****************************************************************************
|
---|
254 | generate a new TDB_DATA key for storing a printer security descriptor
|
---|
255 | ****************************************************************************/
|
---|
256 |
|
---|
257 | static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
|
---|
258 | const char* sharename )
|
---|
259 | {
|
---|
260 | fstring share;
|
---|
261 | char *keystr = NULL;
|
---|
262 | TDB_DATA key;
|
---|
263 |
|
---|
264 | fstrcpy(share, sharename );
|
---|
265 | strlower_m(share);
|
---|
266 |
|
---|
267 | keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
|
---|
268 | key = string_term_tdb_data(keystr ? keystr : "");
|
---|
269 |
|
---|
270 | return key;
|
---|
271 | }
|
---|
272 |
|
---|
273 | /****************************************************************************
|
---|
274 | ****************************************************************************/
|
---|
275 |
|
---|
276 | static bool upgrade_to_version_3(void)
|
---|
277 | {
|
---|
278 | TDB_DATA kbuf, newkey, dbuf;
|
---|
279 |
|
---|
280 | DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
|
---|
281 |
|
---|
282 | for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
|
---|
283 | newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
|
---|
284 |
|
---|
285 | dbuf = tdb_fetch(tdb_drivers, kbuf);
|
---|
286 |
|
---|
287 | if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
|
---|
288 | DEBUG(0,("upgrade_to_version_3:moving form\n"));
|
---|
289 | if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
|
---|
290 | SAFE_FREE(dbuf.dptr);
|
---|
291 | DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
|
---|
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 form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
|
---|
297 | return False;
|
---|
298 | }
|
---|
299 | }
|
---|
300 |
|
---|
301 | if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
|
---|
302 | DEBUG(0,("upgrade_to_version_3:moving printer\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 printer. 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 printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
|
---|
311 | return False;
|
---|
312 | }
|
---|
313 | }
|
---|
314 |
|
---|
315 | if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
|
---|
316 | DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
|
---|
317 | if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
|
---|
318 | SAFE_FREE(dbuf.dptr);
|
---|
319 | DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
|
---|
320 | return False;
|
---|
321 | }
|
---|
322 | if (tdb_delete(tdb_drivers, kbuf) != 0) {
|
---|
323 | SAFE_FREE(dbuf.dptr);
|
---|
324 | DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
|
---|
325 | return False;
|
---|
326 | }
|
---|
327 | }
|
---|
328 |
|
---|
329 | SAFE_FREE(dbuf.dptr);
|
---|
330 | }
|
---|
331 |
|
---|
332 | return True;
|
---|
333 | }
|
---|
334 |
|
---|
335 | /*******************************************************************
|
---|
336 | Fix an issue with security descriptors. Printer sec_desc must
|
---|
337 | use more than the generic bits that were previously used
|
---|
338 | in <= 3.0.14a. They must also have a owner and group SID assigned.
|
---|
339 | Otherwise, any printers than have been migrated to a Windows
|
---|
340 | host using printmig.exe will not be accessible.
|
---|
341 | *******************************************************************/
|
---|
342 |
|
---|
343 | static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
|
---|
344 | TDB_DATA data, void *state )
|
---|
345 | {
|
---|
346 | prs_struct ps;
|
---|
347 | SEC_DESC_BUF *sd_orig = NULL;
|
---|
348 | SEC_DESC_BUF *sd_new, *sd_store;
|
---|
349 | SEC_DESC *sec, *new_sec;
|
---|
350 | TALLOC_CTX *ctx = state;
|
---|
351 | int result, i;
|
---|
352 | uint32 sd_size;
|
---|
353 | size_t size_new_sec;
|
---|
354 |
|
---|
355 | if (!data.dptr || data.dsize == 0) {
|
---|
356 | return 0;
|
---|
357 | }
|
---|
358 |
|
---|
359 | if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
|
---|
360 | return 0;
|
---|
361 | }
|
---|
362 |
|
---|
363 | /* upgrade the security descriptor */
|
---|
364 |
|
---|
365 | ZERO_STRUCT( ps );
|
---|
366 |
|
---|
367 | prs_init_empty( &ps, ctx, UNMARSHALL );
|
---|
368 | prs_give_memory( &ps, (char *)data.dptr, data.dsize, False );
|
---|
369 |
|
---|
370 | if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
|
---|
371 | /* delete bad entries */
|
---|
372 | DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
|
---|
373 | (const char *)key.dptr ));
|
---|
374 | tdb_delete( tdb_printers, key );
|
---|
375 | prs_mem_free( &ps );
|
---|
376 | return 0;
|
---|
377 | }
|
---|
378 |
|
---|
379 | if (!sd_orig) {
|
---|
380 | prs_mem_free( &ps );
|
---|
381 | return 0;
|
---|
382 | }
|
---|
383 | sec = sd_orig->sd;
|
---|
384 |
|
---|
385 | /* is this even valid? */
|
---|
386 |
|
---|
387 | if ( !sec->dacl ) {
|
---|
388 | prs_mem_free( &ps );
|
---|
389 | return 0;
|
---|
390 | }
|
---|
391 |
|
---|
392 | /* update access masks */
|
---|
393 |
|
---|
394 | for ( i=0; i<sec->dacl->num_aces; i++ ) {
|
---|
395 | switch ( sec->dacl->aces[i].access_mask ) {
|
---|
396 | case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
|
---|
397 | sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
|
---|
398 | break;
|
---|
399 |
|
---|
400 | case GENERIC_ALL_ACCESS:
|
---|
401 | sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
|
---|
402 | break;
|
---|
403 |
|
---|
404 | case READ_CONTROL_ACCESS:
|
---|
405 | sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
|
---|
406 |
|
---|
407 | default: /* no change */
|
---|
408 | break;
|
---|
409 | }
|
---|
410 | }
|
---|
411 |
|
---|
412 | /* create a new SEC_DESC with the appropriate owner and group SIDs */
|
---|
413 |
|
---|
414 | new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
|
---|
415 | &global_sid_Builtin_Administrators,
|
---|
416 | &global_sid_Builtin_Administrators,
|
---|
417 | NULL, NULL, &size_new_sec );
|
---|
418 | if (!new_sec) {
|
---|
419 | prs_mem_free( &ps );
|
---|
420 | return 0;
|
---|
421 | }
|
---|
422 | sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
|
---|
423 | if (!sd_new) {
|
---|
424 | prs_mem_free( &ps );
|
---|
425 | return 0;
|
---|
426 | }
|
---|
427 |
|
---|
428 | if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
|
---|
429 | DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
|
---|
430 | prs_mem_free( &ps );
|
---|
431 | return 0;
|
---|
432 | }
|
---|
433 |
|
---|
434 | prs_mem_free( &ps );
|
---|
435 |
|
---|
436 | /* store it back */
|
---|
437 |
|
---|
438 | sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
|
---|
439 | + sizeof(SEC_DESC_BUF);
|
---|
440 | if ( !prs_init(&ps, sd_size, ctx, MARSHALL) ) {
|
---|
441 | DEBUG(0,("sec_desc_upg_fn: Failed to allocate prs memory for %s\n", key.dptr ));
|
---|
442 | return 0;
|
---|
443 | }
|
---|
444 |
|
---|
445 | if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
|
---|
446 | DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
|
---|
447 | prs_mem_free( &ps );
|
---|
448 | return 0;
|
---|
449 | }
|
---|
450 |
|
---|
451 | data.dptr = (uint8 *)prs_data_p( &ps );
|
---|
452 | data.dsize = sd_size;
|
---|
453 |
|
---|
454 | result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
|
---|
455 |
|
---|
456 | prs_mem_free( &ps );
|
---|
457 |
|
---|
458 | /* 0 to continue and non-zero to stop traversal */
|
---|
459 |
|
---|
460 | return (result == -1);
|
---|
461 | }
|
---|
462 |
|
---|
463 | /*******************************************************************
|
---|
464 | *******************************************************************/
|
---|
465 |
|
---|
466 | static bool upgrade_to_version_4(void)
|
---|
467 | {
|
---|
468 | TALLOC_CTX *ctx;
|
---|
469 | int result;
|
---|
470 |
|
---|
471 | DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
|
---|
472 |
|
---|
473 | if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
|
---|
474 | return False;
|
---|
475 |
|
---|
476 | result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
|
---|
477 |
|
---|
478 | talloc_destroy( ctx );
|
---|
479 |
|
---|
480 | return ( result != -1 );
|
---|
481 | }
|
---|
482 |
|
---|
483 | /*******************************************************************
|
---|
484 | Fix an issue with security descriptors. Printer sec_desc must
|
---|
485 | use more than the generic bits that were previously used
|
---|
486 | in <= 3.0.14a. They must also have a owner and group SID assigned.
|
---|
487 | Otherwise, any printers than have been migrated to a Windows
|
---|
488 | host using printmig.exe will not be accessible.
|
---|
489 | *******************************************************************/
|
---|
490 |
|
---|
491 | static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
|
---|
492 | TDB_DATA data, void *state )
|
---|
493 | {
|
---|
494 | TALLOC_CTX *ctx = talloc_tos();
|
---|
495 | TDB_DATA new_key;
|
---|
496 |
|
---|
497 | if (!data.dptr || data.dsize == 0)
|
---|
498 | return 0;
|
---|
499 |
|
---|
500 | /* upgrade printer records and security descriptors */
|
---|
501 |
|
---|
502 | if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
|
---|
503 | new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
|
---|
504 | }
|
---|
505 | else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
|
---|
506 | new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
|
---|
507 | }
|
---|
508 | else {
|
---|
509 | /* ignore this record */
|
---|
510 | return 0;
|
---|
511 | }
|
---|
512 |
|
---|
513 | /* delete the original record and store under the normalized key */
|
---|
514 |
|
---|
515 | if ( tdb_delete( the_tdb, key ) != 0 ) {
|
---|
516 | DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
|
---|
517 | key.dptr));
|
---|
518 | return 1;
|
---|
519 | }
|
---|
520 |
|
---|
521 | if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
|
---|
522 | DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
|
---|
523 | key.dptr));
|
---|
524 | return 1;
|
---|
525 | }
|
---|
526 |
|
---|
527 | return 0;
|
---|
528 | }
|
---|
529 |
|
---|
530 | /*******************************************************************
|
---|
531 | *******************************************************************/
|
---|
532 |
|
---|
533 | static bool upgrade_to_version_5(void)
|
---|
534 | {
|
---|
535 | TALLOC_CTX *ctx;
|
---|
536 | int result;
|
---|
537 |
|
---|
538 | DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
|
---|
539 |
|
---|
540 | if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
|
---|
541 | return False;
|
---|
542 |
|
---|
543 | result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
|
---|
544 |
|
---|
545 | talloc_destroy( ctx );
|
---|
546 |
|
---|
547 | return ( result != -1 );
|
---|
548 | }
|
---|
549 |
|
---|
550 | /****************************************************************************
|
---|
551 | Open the NT printing tdbs. Done once before fork().
|
---|
552 | ****************************************************************************/
|
---|
553 |
|
---|
554 | bool nt_printing_init(struct messaging_context *msg_ctx)
|
---|
555 | {
|
---|
556 | const char *vstring = "INFO/version";
|
---|
557 | WERROR win_rc;
|
---|
558 | int32 vers_id;
|
---|
559 |
|
---|
560 | if ( tdb_drivers && tdb_printers && tdb_forms )
|
---|
561 | return True;
|
---|
562 |
|
---|
563 | if (tdb_drivers)
|
---|
564 | tdb_close(tdb_drivers);
|
---|
565 | tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
|
---|
566 | if (!tdb_drivers) {
|
---|
567 | DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
|
---|
568 | state_path("ntdrivers.tdb"), strerror(errno) ));
|
---|
569 | return False;
|
---|
570 | }
|
---|
571 |
|
---|
572 | if (tdb_printers)
|
---|
573 | tdb_close(tdb_printers);
|
---|
574 | tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
|
---|
575 | if (!tdb_printers) {
|
---|
576 | DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
|
---|
577 | state_path("ntprinters.tdb"), strerror(errno) ));
|
---|
578 | return False;
|
---|
579 | }
|
---|
580 |
|
---|
581 | if (tdb_forms)
|
---|
582 | tdb_close(tdb_forms);
|
---|
583 | tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
|
---|
584 | if (!tdb_forms) {
|
---|
585 | DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
|
---|
586 | state_path("ntforms.tdb"), strerror(errno) ));
|
---|
587 | return False;
|
---|
588 | }
|
---|
589 |
|
---|
590 | /* handle a Samba upgrade */
|
---|
591 |
|
---|
592 | vers_id = tdb_fetch_int32(tdb_drivers, vstring);
|
---|
593 | if (vers_id == -1) {
|
---|
594 | DEBUG(10, ("Fresh database\n"));
|
---|
595 | tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
|
---|
596 | vers_id = NTDRIVERS_DATABASE_VERSION_5;
|
---|
597 | }
|
---|
598 |
|
---|
599 | if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
|
---|
600 |
|
---|
601 | if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
|
---|
602 | if (!upgrade_to_version_3())
|
---|
603 | return False;
|
---|
604 | tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
|
---|
605 | vers_id = NTDRIVERS_DATABASE_VERSION_3;
|
---|
606 | }
|
---|
607 |
|
---|
608 | if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
|
---|
609 | /* Written on a bigendian machine with old fetch_int code. Save as le. */
|
---|
610 | /* The only upgrade between V2 and V3 is to save the version in little-endian. */
|
---|
611 | tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
|
---|
612 | vers_id = NTDRIVERS_DATABASE_VERSION_3;
|
---|
613 | }
|
---|
614 |
|
---|
615 | if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
|
---|
616 | if ( !upgrade_to_version_4() )
|
---|
617 | return False;
|
---|
618 | tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
|
---|
619 | vers_id = NTDRIVERS_DATABASE_VERSION_4;
|
---|
620 | }
|
---|
621 |
|
---|
622 | if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
|
---|
623 | if ( !upgrade_to_version_5() )
|
---|
624 | return False;
|
---|
625 | tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
|
---|
626 | vers_id = NTDRIVERS_DATABASE_VERSION_5;
|
---|
627 | }
|
---|
628 |
|
---|
629 |
|
---|
630 | if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
|
---|
631 | DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
|
---|
632 | return False;
|
---|
633 | }
|
---|
634 | }
|
---|
635 |
|
---|
636 | update_c_setprinter(True);
|
---|
637 |
|
---|
638 | /*
|
---|
639 | * register callback to handle updating printers as new
|
---|
640 | * drivers are installed
|
---|
641 | */
|
---|
642 |
|
---|
643 | messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
|
---|
644 | do_drv_upgrade_printer);
|
---|
645 |
|
---|
646 | /*
|
---|
647 | * register callback to handle updating printer data
|
---|
648 | * when a driver is initialized
|
---|
649 | */
|
---|
650 |
|
---|
651 | messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
|
---|
652 | reset_all_printerdata);
|
---|
653 |
|
---|
654 | /* of course, none of the message callbacks matter if you don't
|
---|
655 | tell messages.c that you interested in receiving PRINT_GENERAL
|
---|
656 | msgs. This is done in claim_connection() */
|
---|
657 |
|
---|
658 |
|
---|
659 | if ( lp_security() == SEC_ADS ) {
|
---|
660 | win_rc = check_published_printers();
|
---|
661 | if (!W_ERROR_IS_OK(win_rc))
|
---|
662 | DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
|
---|
663 | }
|
---|
664 |
|
---|
665 | return True;
|
---|
666 | }
|
---|
667 |
|
---|
668 | /*******************************************************************
|
---|
669 | Function to allow filename parsing "the old way".
|
---|
670 | ********************************************************************/
|
---|
671 |
|
---|
672 | static char *driver_unix_convert(connection_struct *conn,
|
---|
673 | const char *old_name,
|
---|
674 | SMB_STRUCT_STAT *pst)
|
---|
675 | {
|
---|
676 | TALLOC_CTX *ctx = talloc_tos();
|
---|
677 | char *name = talloc_strdup(ctx, old_name);
|
---|
678 | char *new_name = NULL;
|
---|
679 |
|
---|
680 | if (!name) {
|
---|
681 | return NULL;
|
---|
682 | }
|
---|
683 | unix_format(name);
|
---|
684 | name = unix_clean_name(ctx, name);
|
---|
685 | if (!name) {
|
---|
686 | return NULL;
|
---|
687 | }
|
---|
688 | trim_string(name,"/","/");
|
---|
689 | unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
|
---|
690 | return new_name;
|
---|
691 | }
|
---|
692 |
|
---|
693 | /*******************************************************************
|
---|
694 | tdb traversal function for counting printers.
|
---|
695 | ********************************************************************/
|
---|
696 |
|
---|
697 | static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
|
---|
698 | TDB_DATA data, void *context)
|
---|
699 | {
|
---|
700 | int *printer_count = (int*)context;
|
---|
701 |
|
---|
702 | if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
|
---|
703 | (*printer_count)++;
|
---|
704 | DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
|
---|
705 | }
|
---|
706 |
|
---|
707 | return 0;
|
---|
708 | }
|
---|
709 |
|
---|
710 | /*******************************************************************
|
---|
711 | Update the spooler global c_setprinter. This variable is initialized
|
---|
712 | when the parent smbd starts with the number of existing printers. It
|
---|
713 | is monotonically increased by the current number of printers *after*
|
---|
714 | each add or delete printer RPC. Only Microsoft knows why... JRR020119
|
---|
715 | ********************************************************************/
|
---|
716 |
|
---|
717 | uint32 update_c_setprinter(bool initialize)
|
---|
718 | {
|
---|
719 | int32 c_setprinter;
|
---|
720 | int32 printer_count = 0;
|
---|
721 |
|
---|
722 | tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
|
---|
723 |
|
---|
724 | /* Traverse the tdb, counting the printers */
|
---|
725 | tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
|
---|
726 |
|
---|
727 | /* If initializing, set c_setprinter to current printers count
|
---|
728 | * otherwise, bump it by the current printer count
|
---|
729 | */
|
---|
730 | if (!initialize)
|
---|
731 | c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
|
---|
732 | else
|
---|
733 | c_setprinter = printer_count;
|
---|
734 |
|
---|
735 | DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
|
---|
736 | tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
|
---|
737 |
|
---|
738 | tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
|
---|
739 |
|
---|
740 | return (uint32)c_setprinter;
|
---|
741 | }
|
---|
742 |
|
---|
743 | /*******************************************************************
|
---|
744 | Get the spooler global c_setprinter, accounting for initialization.
|
---|
745 | ********************************************************************/
|
---|
746 |
|
---|
747 | uint32 get_c_setprinter(void)
|
---|
748 | {
|
---|
749 | int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
|
---|
750 |
|
---|
751 | if (c_setprinter == (int32)-1)
|
---|
752 | c_setprinter = update_c_setprinter(True);
|
---|
753 |
|
---|
754 | DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
|
---|
755 |
|
---|
756 | return (uint32)c_setprinter;
|
---|
757 | }
|
---|
758 |
|
---|
759 | /****************************************************************************
|
---|
760 | Get builtin form struct list.
|
---|
761 | ****************************************************************************/
|
---|
762 |
|
---|
763 | int get_builtin_ntforms(nt_forms_struct **list)
|
---|
764 | {
|
---|
765 | *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
|
---|
766 | if (!*list) {
|
---|
767 | return 0;
|
---|
768 | }
|
---|
769 | return sizeof(default_forms) / sizeof(default_forms[0]);
|
---|
770 | }
|
---|
771 |
|
---|
772 | /****************************************************************************
|
---|
773 | get a builtin form struct
|
---|
774 | ****************************************************************************/
|
---|
775 |
|
---|
776 | bool get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
|
---|
777 | {
|
---|
778 | int i,count;
|
---|
779 | fstring form_name;
|
---|
780 | unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
|
---|
781 | DEBUGADD(6,("Looking for builtin form %s \n", form_name));
|
---|
782 | count = sizeof(default_forms) / sizeof(default_forms[0]);
|
---|
783 | for (i=0;i<count;i++) {
|
---|
784 | if (strequal(form_name,default_forms[i].name)) {
|
---|
785 | DEBUGADD(6,("Found builtin form %s \n", form_name));
|
---|
786 | memcpy(form,&default_forms[i],sizeof(*form));
|
---|
787 | break;
|
---|
788 | }
|
---|
789 | }
|
---|
790 |
|
---|
791 | return (i !=count);
|
---|
792 | }
|
---|
793 |
|
---|
794 | /****************************************************************************
|
---|
795 | get a form struct list.
|
---|
796 | ****************************************************************************/
|
---|
797 |
|
---|
798 | int get_ntforms(nt_forms_struct **list)
|
---|
799 | {
|
---|
800 | TDB_DATA kbuf, newkey, dbuf;
|
---|
801 | nt_forms_struct form;
|
---|
802 | int ret;
|
---|
803 | int i;
|
---|
804 | int n = 0;
|
---|
805 |
|
---|
806 | *list = NULL;
|
---|
807 |
|
---|
808 | for (kbuf = tdb_firstkey(tdb_forms);
|
---|
809 | kbuf.dptr;
|
---|
810 | newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
|
---|
811 | {
|
---|
812 | if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
|
---|
813 | continue;
|
---|
814 |
|
---|
815 | dbuf = tdb_fetch(tdb_forms, kbuf);
|
---|
816 | if (!dbuf.dptr)
|
---|
817 | continue;
|
---|
818 |
|
---|
819 | fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
|
---|
820 | ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
|
---|
821 | &i, &form.flag, &form.width, &form.length, &form.left,
|
---|
822 | &form.top, &form.right, &form.bottom);
|
---|
823 | SAFE_FREE(dbuf.dptr);
|
---|
824 | if (ret != dbuf.dsize)
|
---|
825 | continue;
|
---|
826 |
|
---|
827 | *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
|
---|
828 | if (!*list) {
|
---|
829 | DEBUG(0,("get_ntforms: Realloc fail.\n"));
|
---|
830 | return 0;
|
---|
831 | }
|
---|
832 | (*list)[n] = form;
|
---|
833 | n++;
|
---|
834 | }
|
---|
835 |
|
---|
836 |
|
---|
837 | return n;
|
---|
838 | }
|
---|
839 |
|
---|
840 | /****************************************************************************
|
---|
841 | write a form struct list
|
---|
842 | ****************************************************************************/
|
---|
843 |
|
---|
844 | int write_ntforms(nt_forms_struct **list, int number)
|
---|
845 | {
|
---|
846 | TALLOC_CTX *ctx = talloc_tos();
|
---|
847 | char *buf = NULL;
|
---|
848 | char *key = NULL;
|
---|
849 | int len;
|
---|
850 | TDB_DATA dbuf;
|
---|
851 | int i;
|
---|
852 |
|
---|
853 | for (i=0;i<number;i++) {
|
---|
854 | /* save index, so list is rebuilt in correct order */
|
---|
855 | len = tdb_pack(NULL, 0, "dddddddd",
|
---|
856 | i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
|
---|
857 | (*list)[i].left, (*list)[i].top, (*list)[i].right,
|
---|
858 | (*list)[i].bottom);
|
---|
859 | if (!len) {
|
---|
860 | continue;
|
---|
861 | }
|
---|
862 | buf = TALLOC_ARRAY(ctx, char, len);
|
---|
863 | if (!buf) {
|
---|
864 | return 0;
|
---|
865 | }
|
---|
866 | len = tdb_pack((uint8 *)buf, len, "dddddddd",
|
---|
867 | i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
|
---|
868 | (*list)[i].left, (*list)[i].top, (*list)[i].right,
|
---|
869 | (*list)[i].bottom);
|
---|
870 | key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
|
---|
871 | if (!key) {
|
---|
872 | return 0;
|
---|
873 | }
|
---|
874 | dbuf.dsize = len;
|
---|
875 | dbuf.dptr = (uint8 *)buf;
|
---|
876 | if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
|
---|
877 | TALLOC_FREE(key);
|
---|
878 | TALLOC_FREE(buf);
|
---|
879 | break;
|
---|
880 | }
|
---|
881 | TALLOC_FREE(key);
|
---|
882 | TALLOC_FREE(buf);
|
---|
883 | }
|
---|
884 |
|
---|
885 | return i;
|
---|
886 | }
|
---|
887 |
|
---|
888 | /****************************************************************************
|
---|
889 | add a form struct at the end of the list
|
---|
890 | ****************************************************************************/
|
---|
891 | bool add_a_form(nt_forms_struct **list, const FORM *form, int *count)
|
---|
892 | {
|
---|
893 | int n=0;
|
---|
894 | bool update;
|
---|
895 | fstring form_name;
|
---|
896 |
|
---|
897 | /*
|
---|
898 | * NT tries to add forms even when
|
---|
899 | * they are already in the base
|
---|
900 | * only update the values if already present
|
---|
901 | */
|
---|
902 |
|
---|
903 | update=False;
|
---|
904 |
|
---|
905 | unistr2_to_ascii(form_name, &form->name, sizeof(form_name));
|
---|
906 | for (n=0; n<*count; n++) {
|
---|
907 | if ( strequal((*list)[n].name, form_name) ) {
|
---|
908 | update=True;
|
---|
909 | break;
|
---|
910 | }
|
---|
911 | }
|
---|
912 |
|
---|
913 | if (update==False) {
|
---|
914 | if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
|
---|
915 | DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
|
---|
916 | return False;
|
---|
917 | }
|
---|
918 | unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name));
|
---|
919 | (*count)++;
|
---|
920 | }
|
---|
921 |
|
---|
922 | (*list)[n].flag=form->flags;
|
---|
923 | (*list)[n].width=form->size_x;
|
---|
924 | (*list)[n].length=form->size_y;
|
---|
925 | (*list)[n].left=form->left;
|
---|
926 | (*list)[n].top=form->top;
|
---|
927 | (*list)[n].right=form->right;
|
---|
928 | (*list)[n].bottom=form->bottom;
|
---|
929 |
|
---|
930 | DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
|
---|
931 | update ? "updated" : "added", form_name));
|
---|
932 |
|
---|
933 | return True;
|
---|
934 | }
|
---|
935 |
|
---|
936 | /****************************************************************************
|
---|
937 | Delete a named form struct.
|
---|
938 | ****************************************************************************/
|
---|
939 |
|
---|
940 | bool delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
|
---|
941 | {
|
---|
942 | char *key = NULL;
|
---|
943 | int n=0;
|
---|
944 | fstring form_name;
|
---|
945 |
|
---|
946 | *ret = WERR_OK;
|
---|
947 |
|
---|
948 | unistr2_to_ascii(form_name, del_name, sizeof(form_name));
|
---|
949 |
|
---|
950 | for (n=0; n<*count; n++) {
|
---|
951 | if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
|
---|
952 | DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
|
---|
953 | break;
|
---|
954 | }
|
---|
955 | }
|
---|
956 |
|
---|
957 | if (n == *count) {
|
---|
958 | DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
|
---|
959 | *ret = WERR_INVALID_PARAM;
|
---|
960 | return False;
|
---|
961 | }
|
---|
962 |
|
---|
963 | if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
|
---|
964 | *ret = WERR_NOMEM;
|
---|
965 | return false;
|
---|
966 | }
|
---|
967 | if (tdb_delete_bystring(tdb_forms, key) != 0) {
|
---|
968 | SAFE_FREE(key);
|
---|
969 | *ret = WERR_NOMEM;
|
---|
970 | return False;
|
---|
971 | }
|
---|
972 | SAFE_FREE(key);
|
---|
973 | return true;
|
---|
974 | }
|
---|
975 |
|
---|
976 | /****************************************************************************
|
---|
977 | Update a form struct.
|
---|
978 | ****************************************************************************/
|
---|
979 |
|
---|
980 | void update_a_form(nt_forms_struct **list, const FORM *form, int count)
|
---|
981 | {
|
---|
982 | int n=0;
|
---|
983 | fstring form_name;
|
---|
984 | unistr2_to_ascii(form_name, &(form->name), sizeof(form_name));
|
---|
985 |
|
---|
986 | DEBUG(106, ("[%s]\n", form_name));
|
---|
987 | for (n=0; n<count; n++) {
|
---|
988 | DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
|
---|
989 | if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
|
---|
990 | break;
|
---|
991 | }
|
---|
992 |
|
---|
993 | if (n==count) return;
|
---|
994 |
|
---|
995 | (*list)[n].flag=form->flags;
|
---|
996 | (*list)[n].width=form->size_x;
|
---|
997 | (*list)[n].length=form->size_y;
|
---|
998 | (*list)[n].left=form->left;
|
---|
999 | (*list)[n].top=form->top;
|
---|
1000 | (*list)[n].right=form->right;
|
---|
1001 | (*list)[n].bottom=form->bottom;
|
---|
1002 | }
|
---|
1003 |
|
---|
1004 | /****************************************************************************
|
---|
1005 | Get the nt drivers list.
|
---|
1006 | Traverse the database and look-up the matching names.
|
---|
1007 | ****************************************************************************/
|
---|
1008 | int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
|
---|
1009 | {
|
---|
1010 | int total=0;
|
---|
1011 | const char *short_archi;
|
---|
1012 | char *key = NULL;
|
---|
1013 | TDB_DATA kbuf, newkey;
|
---|
1014 |
|
---|
1015 | short_archi = get_short_archi(architecture);
|
---|
1016 | if (!short_archi) {
|
---|
1017 | return 0;
|
---|
1018 | }
|
---|
1019 |
|
---|
1020 | if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
|
---|
1021 | short_archi, version) < 0) {
|
---|
1022 | return 0;
|
---|
1023 | }
|
---|
1024 |
|
---|
1025 | for (kbuf = tdb_firstkey(tdb_drivers);
|
---|
1026 | kbuf.dptr;
|
---|
1027 | newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
|
---|
1028 |
|
---|
1029 | if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
|
---|
1030 | continue;
|
---|
1031 |
|
---|
1032 | if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
|
---|
1033 | DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
|
---|
1034 | SAFE_FREE(key);
|
---|
1035 | return -1;
|
---|
1036 | }
|
---|
1037 |
|
---|
1038 | fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
|
---|
1039 | total++;
|
---|
1040 | }
|
---|
1041 |
|
---|
1042 | SAFE_FREE(key);
|
---|
1043 | return(total);
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 | /****************************************************************************
|
---|
1047 | Function to do the mapping between the long architecture name and
|
---|
1048 | the short one.
|
---|
1049 | ****************************************************************************/
|
---|
1050 |
|
---|
1051 | const char *get_short_archi(const char *long_archi)
|
---|
1052 | {
|
---|
1053 | int i=-1;
|
---|
1054 |
|
---|
1055 | DEBUG(107,("Getting architecture dependant directory\n"));
|
---|
1056 | do {
|
---|
1057 | i++;
|
---|
1058 | } while ( (archi_table[i].long_archi!=NULL ) &&
|
---|
1059 | StrCaseCmp(long_archi, archi_table[i].long_archi) );
|
---|
1060 |
|
---|
1061 | if (archi_table[i].long_archi==NULL) {
|
---|
1062 | DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
|
---|
1063 | return NULL;
|
---|
1064 | }
|
---|
1065 |
|
---|
1066 | /* this might be client code - but shouldn't this be an fstrcpy etc? */
|
---|
1067 |
|
---|
1068 | DEBUGADD(108,("index: [%d]\n", i));
|
---|
1069 | DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
|
---|
1070 | DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
|
---|
1071 |
|
---|
1072 | return archi_table[i].short_archi;
|
---|
1073 | }
|
---|
1074 |
|
---|
1075 | /****************************************************************************
|
---|
1076 | Version information in Microsoft files is held in a VS_VERSION_INFO structure.
|
---|
1077 | There are two case to be covered here: PE (Portable Executable) and NE (New
|
---|
1078 | Executable) files. Both files support the same INFO structure, but PE files
|
---|
1079 | store the signature in unicode, and NE files store it as !unicode.
|
---|
1080 | returns -1 on error, 1 on version info found, and 0 on no version info found.
|
---|
1081 | ****************************************************************************/
|
---|
1082 |
|
---|
1083 | static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
|
---|
1084 | {
|
---|
1085 | int i;
|
---|
1086 | char *buf = NULL;
|
---|
1087 | ssize_t byte_count;
|
---|
1088 |
|
---|
1089 | if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
|
---|
1090 | DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
|
---|
1091 | fname, DOS_HEADER_SIZE));
|
---|
1092 | goto error_exit;
|
---|
1093 | }
|
---|
1094 |
|
---|
1095 | if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
|
---|
1096 | DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
|
---|
1097 | fname, (unsigned long)byte_count));
|
---|
1098 | goto no_version_info;
|
---|
1099 | }
|
---|
1100 |
|
---|
1101 | /* Is this really a DOS header? */
|
---|
1102 | if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
|
---|
1103 | DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
|
---|
1104 | fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
|
---|
1105 | goto no_version_info;
|
---|
1106 | }
|
---|
1107 |
|
---|
1108 | /* Skip OEM header (if any) and the DOS stub to start of Windows header */
|
---|
1109 | if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
|
---|
1110 | DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
|
---|
1111 | fname, errno));
|
---|
1112 | /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
|
---|
1113 | goto no_version_info;
|
---|
1114 | }
|
---|
1115 |
|
---|
1116 | /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
|
---|
1117 | if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
|
---|
1118 | DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
|
---|
1119 | fname, (unsigned long)byte_count));
|
---|
1120 | /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
|
---|
1121 | goto no_version_info;
|
---|
1122 | }
|
---|
1123 |
|
---|
1124 | /* The header may be a PE (Portable Executable) or an NE (New Executable) */
|
---|
1125 | if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
|
---|
1126 | unsigned int num_sections;
|
---|
1127 | unsigned int section_table_bytes;
|
---|
1128 |
|
---|
1129 | /* Just skip over optional header to get to section table */
|
---|
1130 | if (SMB_VFS_LSEEK(fsp,
|
---|
1131 | SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
|
---|
1132 | SEEK_CUR) == (SMB_OFF_T)-1) {
|
---|
1133 | DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
|
---|
1134 | fname, errno));
|
---|
1135 | goto error_exit;
|
---|
1136 | }
|
---|
1137 |
|
---|
1138 | /* get the section table */
|
---|
1139 | num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
|
---|
1140 | section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
|
---|
1141 | if (section_table_bytes == 0)
|
---|
1142 | goto error_exit;
|
---|
1143 |
|
---|
1144 | SAFE_FREE(buf);
|
---|
1145 | if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
|
---|
1146 | DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
|
---|
1147 | fname, section_table_bytes));
|
---|
1148 | goto error_exit;
|
---|
1149 | }
|
---|
1150 |
|
---|
1151 | if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
|
---|
1152 | DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
|
---|
1153 | fname, (unsigned long)byte_count));
|
---|
1154 | goto error_exit;
|
---|
1155 | }
|
---|
1156 |
|
---|
1157 | /* Iterate the section table looking for the resource section ".rsrc" */
|
---|
1158 | for (i = 0; i < num_sections; i++) {
|
---|
1159 | int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
|
---|
1160 |
|
---|
1161 | if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
|
---|
1162 | unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
|
---|
1163 | unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
|
---|
1164 |
|
---|
1165 | if (section_bytes == 0)
|
---|
1166 | goto error_exit;
|
---|
1167 |
|
---|
1168 | SAFE_FREE(buf);
|
---|
1169 | if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
|
---|
1170 | DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
|
---|
1171 | fname, section_bytes));
|
---|
1172 | goto error_exit;
|
---|
1173 | }
|
---|
1174 |
|
---|
1175 | /* Seek to the start of the .rsrc section info */
|
---|
1176 | if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
|
---|
1177 | DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
|
---|
1178 | fname, errno));
|
---|
1179 | goto error_exit;
|
---|
1180 | }
|
---|
1181 |
|
---|
1182 | if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
|
---|
1183 | DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
|
---|
1184 | fname, (unsigned long)byte_count));
|
---|
1185 | goto error_exit;
|
---|
1186 | }
|
---|
1187 |
|
---|
1188 | if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
|
---|
1189 | goto error_exit;
|
---|
1190 |
|
---|
1191 | for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
|
---|
1192 | /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
|
---|
1193 | if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
|
---|
1194 | /* Align to next long address */
|
---|
1195 | int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
|
---|
1196 |
|
---|
1197 | if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
|
---|
1198 | *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
|
---|
1199 | *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
|
---|
1200 |
|
---|
1201 | DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
|
---|
1202 | fname, *major, *minor,
|
---|
1203 | (*major>>16)&0xffff, *major&0xffff,
|
---|
1204 | (*minor>>16)&0xffff, *minor&0xffff));
|
---|
1205 | SAFE_FREE(buf);
|
---|
1206 | return 1;
|
---|
1207 | }
|
---|
1208 | }
|
---|
1209 | }
|
---|
1210 | }
|
---|
1211 | }
|
---|
1212 |
|
---|
1213 | /* Version info not found, fall back to origin date/time */
|
---|
1214 | DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
|
---|
1215 | SAFE_FREE(buf);
|
---|
1216 | return 0;
|
---|
1217 |
|
---|
1218 | } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
|
---|
1219 | if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
|
---|
1220 | DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
|
---|
1221 | fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
|
---|
1222 | /* At this point, we assume the file is in error. It still could be somthing
|
---|
1223 | * else besides a NE file, but it unlikely at this point. */
|
---|
1224 | goto error_exit;
|
---|
1225 | }
|
---|
1226 |
|
---|
1227 | /* Allocate a bit more space to speed up things */
|
---|
1228 | SAFE_FREE(buf);
|
---|
1229 | if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
|
---|
1230 | DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
|
---|
1231 | fname, PE_HEADER_SIZE));
|
---|
1232 | goto error_exit;
|
---|
1233 | }
|
---|
1234 |
|
---|
1235 | /* This is a HACK! I got tired of trying to sort through the messy
|
---|
1236 | * 'NE' file format. If anyone wants to clean this up please have at
|
---|
1237 | * it, but this works. 'NE' files will eventually fade away. JRR */
|
---|
1238 | while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
|
---|
1239 | /* Cover case that should not occur in a well formed 'NE' .dll file */
|
---|
1240 | if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
|
---|
1241 |
|
---|
1242 | for(i=0; i<byte_count; i++) {
|
---|
1243 | /* Fast skip past data that can't possibly match */
|
---|
1244 | if (buf[i] != 'V') continue;
|
---|
1245 |
|
---|
1246 | /* Potential match data crosses buf boundry, move it to beginning
|
---|
1247 | * of buf, and fill the buf with as much as it will hold. */
|
---|
1248 | if (i>byte_count-VS_VERSION_INFO_SIZE) {
|
---|
1249 | int bc;
|
---|
1250 |
|
---|
1251 | memcpy(buf, &buf[i], byte_count-i);
|
---|
1252 | if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
|
---|
1253 | (byte_count-i))) < 0) {
|
---|
1254 |
|
---|
1255 | DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
|
---|
1256 | fname, errno));
|
---|
1257 | goto error_exit;
|
---|
1258 | }
|
---|
1259 |
|
---|
1260 | byte_count = bc + (byte_count - i);
|
---|
1261 | if (byte_count<VS_VERSION_INFO_SIZE) break;
|
---|
1262 |
|
---|
1263 | i = 0;
|
---|
1264 | }
|
---|
1265 |
|
---|
1266 | /* Check that the full signature string and the magic number that
|
---|
1267 | * follows exist (not a perfect solution, but the chances that this
|
---|
1268 | * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
|
---|
1269 | * twice, as it is simpler to read the code. */
|
---|
1270 | if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
|
---|
1271 | /* Compute skip alignment to next long address */
|
---|
1272 | int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
|
---|
1273 | sizeof(VS_SIGNATURE)) & 3;
|
---|
1274 | if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
|
---|
1275 |
|
---|
1276 | *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
|
---|
1277 | *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
|
---|
1278 | DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
|
---|
1279 | fname, *major, *minor,
|
---|
1280 | (*major>>16)&0xffff, *major&0xffff,
|
---|
1281 | (*minor>>16)&0xffff, *minor&0xffff));
|
---|
1282 | SAFE_FREE(buf);
|
---|
1283 | return 1;
|
---|
1284 | }
|
---|
1285 | }
|
---|
1286 | }
|
---|
1287 |
|
---|
1288 | /* Version info not found, fall back to origin date/time */
|
---|
1289 | DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
|
---|
1290 | SAFE_FREE(buf);
|
---|
1291 | return 0;
|
---|
1292 |
|
---|
1293 | } else
|
---|
1294 | /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
|
---|
1295 | DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
|
---|
1296 | fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
|
---|
1297 |
|
---|
1298 | no_version_info:
|
---|
1299 | SAFE_FREE(buf);
|
---|
1300 | return 0;
|
---|
1301 |
|
---|
1302 | error_exit:
|
---|
1303 | SAFE_FREE(buf);
|
---|
1304 | return -1;
|
---|
1305 | }
|
---|
1306 |
|
---|
1307 | /****************************************************************************
|
---|
1308 | Drivers for Microsoft systems contain multiple files. Often, multiple drivers
|
---|
1309 | share one or more files. During the MS installation process files are checked
|
---|
1310 | to insure that only a newer version of a shared file is installed over an
|
---|
1311 | older version. There are several possibilities for this comparison. If there
|
---|
1312 | is no previous version, the new one is newer (obviously). If either file is
|
---|
1313 | missing the version info structure, compare the creation date (on Unix use
|
---|
1314 | the modification date). Otherwise chose the numerically larger version number.
|
---|
1315 | ****************************************************************************/
|
---|
1316 |
|
---|
1317 | static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
|
---|
1318 | {
|
---|
1319 | bool use_version = true;
|
---|
1320 | char *filepath = NULL;
|
---|
1321 |
|
---|
1322 | uint32 new_major;
|
---|
1323 | uint32 new_minor;
|
---|
1324 | time_t new_create_time;
|
---|
1325 |
|
---|
1326 | uint32 old_major;
|
---|
1327 | uint32 old_minor;
|
---|
1328 | time_t old_create_time;
|
---|
1329 |
|
---|
1330 | files_struct *fsp = NULL;
|
---|
1331 | SMB_STRUCT_STAT st;
|
---|
1332 | SMB_STRUCT_STAT stat_buf;
|
---|
1333 |
|
---|
1334 | NTSTATUS status;
|
---|
1335 |
|
---|
1336 | SET_STAT_INVALID(st);
|
---|
1337 | SET_STAT_INVALID(stat_buf);
|
---|
1338 | new_create_time = (time_t)0;
|
---|
1339 | old_create_time = (time_t)0;
|
---|
1340 |
|
---|
1341 | /* Get file version info (if available) for previous file (if it exists) */
|
---|
1342 | filepath = driver_unix_convert(conn,old_file,&stat_buf);
|
---|
1343 | if (!filepath) {
|
---|
1344 | goto error_exit;
|
---|
1345 | }
|
---|
1346 |
|
---|
1347 | status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
|
---|
1348 | FILE_GENERIC_READ,
|
---|
1349 | FILE_SHARE_READ|FILE_SHARE_WRITE,
|
---|
1350 | FILE_OPEN,
|
---|
1351 | 0,
|
---|
1352 | FILE_ATTRIBUTE_NORMAL,
|
---|
1353 | INTERNAL_OPEN_ONLY,
|
---|
1354 | NULL, &fsp);
|
---|
1355 |
|
---|
1356 | if (!NT_STATUS_IS_OK(status)) {
|
---|
1357 | /* Old file not found, so by definition new file is in fact newer */
|
---|
1358 | DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
|
---|
1359 | filepath, errno));
|
---|
1360 | return 1;
|
---|
1361 |
|
---|
1362 | } else {
|
---|
1363 | int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
|
---|
1364 | if (ret == -1) {
|
---|
1365 | goto error_exit;
|
---|
1366 | }
|
---|
1367 |
|
---|
1368 | if (!ret) {
|
---|
1369 | DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
|
---|
1370 | old_file));
|
---|
1371 | use_version = false;
|
---|
1372 | if (SMB_VFS_FSTAT(fsp, &st) == -1) {
|
---|
1373 | goto error_exit;
|
---|
1374 | }
|
---|
1375 | old_create_time = st.st_mtime;
|
---|
1376 | DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
|
---|
1377 | (long)old_create_time));
|
---|
1378 | }
|
---|
1379 | }
|
---|
1380 | close_file(fsp, NORMAL_CLOSE);
|
---|
1381 | fsp = NULL;
|
---|
1382 |
|
---|
1383 | /* Get file version info (if available) for new file */
|
---|
1384 | filepath = driver_unix_convert(conn,new_file,&stat_buf);
|
---|
1385 | if (!filepath) {
|
---|
1386 | goto error_exit;
|
---|
1387 | }
|
---|
1388 |
|
---|
1389 | status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
|
---|
1390 | FILE_GENERIC_READ,
|
---|
1391 | FILE_SHARE_READ|FILE_SHARE_WRITE,
|
---|
1392 | FILE_OPEN,
|
---|
1393 | 0,
|
---|
1394 | FILE_ATTRIBUTE_NORMAL,
|
---|
1395 | INTERNAL_OPEN_ONLY,
|
---|
1396 | NULL, &fsp);
|
---|
1397 |
|
---|
1398 | if (!NT_STATUS_IS_OK(status)) {
|
---|
1399 | /* New file not found, this shouldn't occur if the caller did its job */
|
---|
1400 | DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
|
---|
1401 | filepath, errno));
|
---|
1402 | goto error_exit;
|
---|
1403 |
|
---|
1404 | } else {
|
---|
1405 | int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
|
---|
1406 | if (ret == -1) {
|
---|
1407 | goto error_exit;
|
---|
1408 | }
|
---|
1409 |
|
---|
1410 | if (!ret) {
|
---|
1411 | DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
|
---|
1412 | new_file));
|
---|
1413 | use_version = false;
|
---|
1414 | if (SMB_VFS_FSTAT(fsp, &st) == -1) {
|
---|
1415 | goto error_exit;
|
---|
1416 | }
|
---|
1417 | new_create_time = st.st_mtime;
|
---|
1418 | DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
|
---|
1419 | (long)new_create_time));
|
---|
1420 | }
|
---|
1421 | }
|
---|
1422 | close_file(fsp, NORMAL_CLOSE);
|
---|
1423 | fsp = NULL;
|
---|
1424 |
|
---|
1425 | if (use_version && (new_major != old_major || new_minor != old_minor)) {
|
---|
1426 | /* Compare versions and choose the larger version number */
|
---|
1427 | if (new_major > old_major ||
|
---|
1428 | (new_major == old_major && new_minor > old_minor)) {
|
---|
1429 |
|
---|
1430 | DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
|
---|
1431 | return 1;
|
---|
1432 | }
|
---|
1433 | else {
|
---|
1434 | DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
|
---|
1435 | return 0;
|
---|
1436 | }
|
---|
1437 |
|
---|
1438 | } else {
|
---|
1439 | /* Compare modification time/dates and choose the newest time/date */
|
---|
1440 | if (new_create_time > old_create_time) {
|
---|
1441 | DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
|
---|
1442 | return 1;
|
---|
1443 | }
|
---|
1444 | else {
|
---|
1445 | DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
|
---|
1446 | return 0;
|
---|
1447 | }
|
---|
1448 | }
|
---|
1449 |
|
---|
1450 | error_exit:
|
---|
1451 | if(fsp)
|
---|
1452 | close_file(fsp, NORMAL_CLOSE);
|
---|
1453 | return -1;
|
---|
1454 | }
|
---|
1455 |
|
---|
1456 | /****************************************************************************
|
---|
1457 | Determine the correct cVersion associated with an architecture and driver
|
---|
1458 | ****************************************************************************/
|
---|
1459 | static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
|
---|
1460 | struct current_user *user, WERROR *perr)
|
---|
1461 | {
|
---|
1462 | int cversion;
|
---|
1463 | NTSTATUS nt_status;
|
---|
1464 | char *driverpath = NULL;
|
---|
1465 | DATA_BLOB null_pw;
|
---|
1466 | fstring res_type;
|
---|
1467 | files_struct *fsp = NULL;
|
---|
1468 | SMB_STRUCT_STAT st;
|
---|
1469 | connection_struct *conn;
|
---|
1470 | NTSTATUS status;
|
---|
1471 |
|
---|
1472 | SET_STAT_INVALID(st);
|
---|
1473 |
|
---|
1474 | *perr = WERR_INVALID_PARAM;
|
---|
1475 |
|
---|
1476 | /* If architecture is Windows 95/98/ME, the version is always 0. */
|
---|
1477 | if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
|
---|
1478 | DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
|
---|
1479 | *perr = WERR_OK;
|
---|
1480 | return 0;
|
---|
1481 | }
|
---|
1482 |
|
---|
1483 | /* If architecture is Windows x64, the version is always 3. */
|
---|
1484 | if (strcmp(architecture, SPL_ARCH_X64) == 0) {
|
---|
1485 | DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
|
---|
1486 | *perr = WERR_OK;
|
---|
1487 | return 3;
|
---|
1488 | }
|
---|
1489 |
|
---|
1490 | /*
|
---|
1491 | * Connect to the print$ share under the same account as the user connected
|
---|
1492 | * to the rpc pipe. Note we must still be root to do this.
|
---|
1493 | */
|
---|
1494 |
|
---|
1495 | /* Null password is ok - we are already an authenticated user... */
|
---|
1496 | null_pw = data_blob_null;
|
---|
1497 | fstrcpy(res_type, "A:");
|
---|
1498 | become_root();
|
---|
1499 | conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
|
---|
1500 | unbecome_root();
|
---|
1501 |
|
---|
1502 | if (conn == NULL) {
|
---|
1503 | DEBUG(0,("get_correct_cversion: Unable to connect\n"));
|
---|
1504 | *perr = ntstatus_to_werror(nt_status);
|
---|
1505 | return -1;
|
---|
1506 | }
|
---|
1507 |
|
---|
1508 | /* We are temporarily becoming the connection user. */
|
---|
1509 | if (!become_user(conn, user->vuid)) {
|
---|
1510 | DEBUG(0,("get_correct_cversion: Can't become user!\n"));
|
---|
1511 | *perr = WERR_ACCESS_DENIED;
|
---|
1512 | return -1;
|
---|
1513 | }
|
---|
1514 |
|
---|
1515 | /* Open the driver file (Portable Executable format) and determine the
|
---|
1516 | * deriver the cversion. */
|
---|
1517 | driverpath = talloc_asprintf(talloc_tos(),
|
---|
1518 | "%s/%s",
|
---|
1519 | architecture,
|
---|
1520 | driverpath_in);
|
---|
1521 | if (!driverpath) {
|
---|
1522 | *perr = WERR_NOMEM;
|
---|
1523 | goto error_exit;
|
---|
1524 | }
|
---|
1525 |
|
---|
1526 | driverpath = driver_unix_convert(conn,driverpath,&st);
|
---|
1527 | if (!driverpath) {
|
---|
1528 | *perr = WERR_NOMEM;
|
---|
1529 | goto error_exit;
|
---|
1530 | }
|
---|
1531 |
|
---|
1532 | if (!vfs_file_exist(conn, driverpath, &st)) {
|
---|
1533 | *perr = WERR_BADFILE;
|
---|
1534 | goto error_exit;
|
---|
1535 | }
|
---|
1536 |
|
---|
1537 | status = open_file_ntcreate(conn, NULL, driverpath, &st,
|
---|
1538 | FILE_GENERIC_READ,
|
---|
1539 | FILE_SHARE_READ|FILE_SHARE_WRITE,
|
---|
1540 | FILE_OPEN,
|
---|
1541 | 0,
|
---|
1542 | FILE_ATTRIBUTE_NORMAL,
|
---|
1543 | INTERNAL_OPEN_ONLY,
|
---|
1544 | NULL, &fsp);
|
---|
1545 |
|
---|
1546 | if (!NT_STATUS_IS_OK(status)) {
|
---|
1547 | DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
|
---|
1548 | driverpath, errno));
|
---|
1549 | *perr = WERR_ACCESS_DENIED;
|
---|
1550 | goto error_exit;
|
---|
1551 | } else {
|
---|
1552 | uint32 major;
|
---|
1553 | uint32 minor;
|
---|
1554 | int ret = get_file_version(fsp, driverpath, &major, &minor);
|
---|
1555 | if (ret == -1) goto error_exit;
|
---|
1556 |
|
---|
1557 | if (!ret) {
|
---|
1558 | DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
|
---|
1559 | goto error_exit;
|
---|
1560 | }
|
---|
1561 |
|
---|
1562 | /*
|
---|
1563 | * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
|
---|
1564 | * for more details. Version in this case is not just the version of the
|
---|
1565 | * file, but the version in the sense of kernal mode (2) vs. user mode
|
---|
1566 | * (3) drivers. Other bits of the version fields are the version info.
|
---|
1567 | * JRR 010716
|
---|
1568 | */
|
---|
1569 | cversion = major & 0x0000ffff;
|
---|
1570 | switch (cversion) {
|
---|
1571 | case 2: /* WinNT drivers */
|
---|
1572 | case 3: /* Win2K drivers */
|
---|
1573 | break;
|
---|
1574 |
|
---|
1575 | default:
|
---|
1576 | DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
|
---|
1577 | driverpath, cversion));
|
---|
1578 | goto error_exit;
|
---|
1579 | }
|
---|
1580 |
|
---|
1581 | DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
|
---|
1582 | driverpath, major, minor));
|
---|
1583 | }
|
---|
1584 |
|
---|
1585 | DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
|
---|
1586 | driverpath, cversion));
|
---|
1587 |
|
---|
1588 | close_file(fsp, NORMAL_CLOSE);
|
---|
1589 | close_cnum(conn, user->vuid);
|
---|
1590 | unbecome_user();
|
---|
1591 | *perr = WERR_OK;
|
---|
1592 | return cversion;
|
---|
1593 |
|
---|
1594 |
|
---|
1595 | error_exit:
|
---|
1596 |
|
---|
1597 | if(fsp)
|
---|
1598 | close_file(fsp, NORMAL_CLOSE);
|
---|
1599 |
|
---|
1600 | close_cnum(conn, user->vuid);
|
---|
1601 | unbecome_user();
|
---|
1602 | return -1;
|
---|
1603 | }
|
---|
1604 |
|
---|
1605 | /****************************************************************************
|
---|
1606 | ****************************************************************************/
|
---|
1607 | static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
|
---|
1608 | struct current_user *user)
|
---|
1609 | {
|
---|
1610 | const char *architecture;
|
---|
1611 | fstring new_name;
|
---|
1612 | char *p;
|
---|
1613 | int i;
|
---|
1614 | WERROR err;
|
---|
1615 |
|
---|
1616 | /* clean up the driver name.
|
---|
1617 | * we can get .\driver.dll
|
---|
1618 | * or worse c:\windows\system\driver.dll !
|
---|
1619 | */
|
---|
1620 | /* using an intermediate string to not have overlaping memcpy()'s */
|
---|
1621 | if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
|
---|
1622 | fstrcpy(new_name, p+1);
|
---|
1623 | fstrcpy(driver->driverpath, new_name);
|
---|
1624 | }
|
---|
1625 |
|
---|
1626 | if ((p = strrchr(driver->datafile,'\\')) != NULL) {
|
---|
1627 | fstrcpy(new_name, p+1);
|
---|
1628 | fstrcpy(driver->datafile, new_name);
|
---|
1629 | }
|
---|
1630 |
|
---|
1631 | if ((p = strrchr(driver->configfile,'\\')) != NULL) {
|
---|
1632 | fstrcpy(new_name, p+1);
|
---|
1633 | fstrcpy(driver->configfile, new_name);
|
---|
1634 | }
|
---|
1635 |
|
---|
1636 | if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
|
---|
1637 | fstrcpy(new_name, p+1);
|
---|
1638 | fstrcpy(driver->helpfile, new_name);
|
---|
1639 | }
|
---|
1640 |
|
---|
1641 | if (driver->dependentfiles) {
|
---|
1642 | for (i=0; *driver->dependentfiles[i]; i++) {
|
---|
1643 | if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
|
---|
1644 | fstrcpy(new_name, p+1);
|
---|
1645 | fstrcpy(driver->dependentfiles[i], new_name);
|
---|
1646 | }
|
---|
1647 | }
|
---|
1648 | }
|
---|
1649 |
|
---|
1650 | architecture = get_short_archi(driver->environment);
|
---|
1651 | if (!architecture) {
|
---|
1652 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
1653 | }
|
---|
1654 |
|
---|
1655 | /* jfm:7/16/2000 the client always sends the cversion=0.
|
---|
1656 | * The server should check which version the driver is by reading
|
---|
1657 | * the PE header of driver->driverpath.
|
---|
1658 | *
|
---|
1659 | * For Windows 95/98 the version is 0 (so the value sent is correct)
|
---|
1660 | * For Windows NT (the architecture doesn't matter)
|
---|
1661 | * NT 3.1: cversion=0
|
---|
1662 | * NT 3.5/3.51: cversion=1
|
---|
1663 | * NT 4: cversion=2
|
---|
1664 | * NT2K: cversion=3
|
---|
1665 | */
|
---|
1666 | if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
|
---|
1667 | return err;
|
---|
1668 |
|
---|
1669 | return WERR_OK;
|
---|
1670 | }
|
---|
1671 |
|
---|
1672 | /****************************************************************************
|
---|
1673 | ****************************************************************************/
|
---|
1674 | static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
|
---|
1675 | {
|
---|
1676 | const char *architecture;
|
---|
1677 | fstring new_name;
|
---|
1678 | char *p;
|
---|
1679 | int i;
|
---|
1680 | WERROR err;
|
---|
1681 |
|
---|
1682 | /* clean up the driver name.
|
---|
1683 | * we can get .\driver.dll
|
---|
1684 | * or worse c:\windows\system\driver.dll !
|
---|
1685 | */
|
---|
1686 | /* using an intermediate string to not have overlaping memcpy()'s */
|
---|
1687 | if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
|
---|
1688 | fstrcpy(new_name, p+1);
|
---|
1689 | fstrcpy(driver->driverpath, new_name);
|
---|
1690 | }
|
---|
1691 |
|
---|
1692 | if ((p = strrchr(driver->datafile,'\\')) != NULL) {
|
---|
1693 | fstrcpy(new_name, p+1);
|
---|
1694 | fstrcpy(driver->datafile, new_name);
|
---|
1695 | }
|
---|
1696 |
|
---|
1697 | if ((p = strrchr(driver->configfile,'\\')) != NULL) {
|
---|
1698 | fstrcpy(new_name, p+1);
|
---|
1699 | fstrcpy(driver->configfile, new_name);
|
---|
1700 | }
|
---|
1701 |
|
---|
1702 | if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
|
---|
1703 | fstrcpy(new_name, p+1);
|
---|
1704 | fstrcpy(driver->helpfile, new_name);
|
---|
1705 | }
|
---|
1706 |
|
---|
1707 | if (driver->dependentfiles) {
|
---|
1708 | for (i=0; *driver->dependentfiles[i]; i++) {
|
---|
1709 | if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
|
---|
1710 | fstrcpy(new_name, p+1);
|
---|
1711 | fstrcpy(driver->dependentfiles[i], new_name);
|
---|
1712 | }
|
---|
1713 | }
|
---|
1714 | }
|
---|
1715 |
|
---|
1716 | architecture = get_short_archi(driver->environment);
|
---|
1717 | if (!architecture) {
|
---|
1718 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
1719 | }
|
---|
1720 |
|
---|
1721 | /* jfm:7/16/2000 the client always sends the cversion=0.
|
---|
1722 | * The server should check which version the driver is by reading
|
---|
1723 | * the PE header of driver->driverpath.
|
---|
1724 | *
|
---|
1725 | * For Windows 95/98 the version is 0 (so the value sent is correct)
|
---|
1726 | * For Windows NT (the architecture doesn't matter)
|
---|
1727 | * NT 3.1: cversion=0
|
---|
1728 | * NT 3.5/3.51: cversion=1
|
---|
1729 | * NT 4: cversion=2
|
---|
1730 | * NT2K: cversion=3
|
---|
1731 | */
|
---|
1732 |
|
---|
1733 | if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
|
---|
1734 | return err;
|
---|
1735 |
|
---|
1736 | return WERR_OK;
|
---|
1737 | }
|
---|
1738 |
|
---|
1739 | /****************************************************************************
|
---|
1740 | ****************************************************************************/
|
---|
1741 | WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
|
---|
1742 | uint32 level, struct current_user *user)
|
---|
1743 | {
|
---|
1744 | switch (level) {
|
---|
1745 | case 3:
|
---|
1746 | {
|
---|
1747 | NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
|
---|
1748 | driver=driver_abstract.info_3;
|
---|
1749 | return clean_up_driver_struct_level_3(driver, user);
|
---|
1750 | }
|
---|
1751 | case 6:
|
---|
1752 | {
|
---|
1753 | NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
|
---|
1754 | driver=driver_abstract.info_6;
|
---|
1755 | return clean_up_driver_struct_level_6(driver, user);
|
---|
1756 | }
|
---|
1757 | default:
|
---|
1758 | return WERR_INVALID_PARAM;
|
---|
1759 | }
|
---|
1760 | }
|
---|
1761 |
|
---|
1762 | /****************************************************************************
|
---|
1763 | This function sucks and should be replaced. JRA.
|
---|
1764 | ****************************************************************************/
|
---|
1765 |
|
---|
1766 | static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
|
---|
1767 | {
|
---|
1768 | dst->cversion = src->version;
|
---|
1769 |
|
---|
1770 | fstrcpy( dst->name, src->name);
|
---|
1771 | fstrcpy( dst->environment, src->environment);
|
---|
1772 | fstrcpy( dst->driverpath, src->driverpath);
|
---|
1773 | fstrcpy( dst->datafile, src->datafile);
|
---|
1774 | fstrcpy( dst->configfile, src->configfile);
|
---|
1775 | fstrcpy( dst->helpfile, src->helpfile);
|
---|
1776 | fstrcpy( dst->monitorname, src->monitorname);
|
---|
1777 | fstrcpy( dst->defaultdatatype, src->defaultdatatype);
|
---|
1778 | dst->dependentfiles = src->dependentfiles;
|
---|
1779 | }
|
---|
1780 |
|
---|
1781 | #if 0 /* Debugging function */
|
---|
1782 |
|
---|
1783 | static char* ffmt(unsigned char *c){
|
---|
1784 | int i;
|
---|
1785 | static char ffmt_str[17];
|
---|
1786 |
|
---|
1787 | for (i=0; i<16; i++) {
|
---|
1788 | if ((c[i] < ' ') || (c[i] > '~'))
|
---|
1789 | ffmt_str[i]='.';
|
---|
1790 | else
|
---|
1791 | ffmt_str[i]=c[i];
|
---|
1792 | }
|
---|
1793 | ffmt_str[16]='\0';
|
---|
1794 | return ffmt_str;
|
---|
1795 | }
|
---|
1796 |
|
---|
1797 | #endif
|
---|
1798 |
|
---|
1799 | /****************************************************************************
|
---|
1800 | ****************************************************************************/
|
---|
1801 | WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
|
---|
1802 | struct current_user *user, WERROR *perr)
|
---|
1803 | {
|
---|
1804 | NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
|
---|
1805 | NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
|
---|
1806 | const char *architecture;
|
---|
1807 | char *new_dir = NULL;
|
---|
1808 | char *old_name = NULL;
|
---|
1809 | char *new_name = NULL;
|
---|
1810 | DATA_BLOB null_pw;
|
---|
1811 | connection_struct *conn;
|
---|
1812 | NTSTATUS nt_status;
|
---|
1813 | fstring res_type;
|
---|
1814 | SMB_STRUCT_STAT st;
|
---|
1815 | int i;
|
---|
1816 | TALLOC_CTX *ctx = talloc_tos();
|
---|
1817 | int ver = 0;
|
---|
1818 |
|
---|
1819 | *perr = WERR_OK;
|
---|
1820 |
|
---|
1821 | if (level==3)
|
---|
1822 | driver=driver_abstract.info_3;
|
---|
1823 | else if (level==6) {
|
---|
1824 | convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
|
---|
1825 | driver = &converted_driver;
|
---|
1826 | } else {
|
---|
1827 | DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
|
---|
1828 | return WERR_UNKNOWN_LEVEL;
|
---|
1829 | }
|
---|
1830 |
|
---|
1831 | architecture = get_short_archi(driver->environment);
|
---|
1832 | if (!architecture) {
|
---|
1833 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
1834 | }
|
---|
1835 |
|
---|
1836 | /*
|
---|
1837 | * Connect to the print$ share under the same account as the user connected to the rpc pipe.
|
---|
1838 | * Note we must be root to do this.
|
---|
1839 | */
|
---|
1840 |
|
---|
1841 | null_pw = data_blob_null;
|
---|
1842 | fstrcpy(res_type, "A:");
|
---|
1843 | become_root();
|
---|
1844 | conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
|
---|
1845 | unbecome_root();
|
---|
1846 |
|
---|
1847 | if (conn == NULL) {
|
---|
1848 | DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
|
---|
1849 | *perr = ntstatus_to_werror(nt_status);
|
---|
1850 | return WERR_NO_SUCH_SHARE;
|
---|
1851 | }
|
---|
1852 |
|
---|
1853 | /*
|
---|
1854 | * Save who we are - we are temporarily becoming the connection user.
|
---|
1855 | */
|
---|
1856 |
|
---|
1857 | if (!become_user(conn, conn->vuid)) {
|
---|
1858 | DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
|
---|
1859 | return WERR_ACCESS_DENIED;
|
---|
1860 | }
|
---|
1861 |
|
---|
1862 | /* WE ARE NOW RUNNING AS USER conn->vuid !!!!! */
|
---|
1863 |
|
---|
1864 | /*
|
---|
1865 | * make the directories version and version\driver_name
|
---|
1866 | * under the architecture directory.
|
---|
1867 | */
|
---|
1868 | DEBUG(5,("Creating first directory\n"));
|
---|
1869 | new_dir = talloc_asprintf(ctx,
|
---|
1870 | "%s/%d",
|
---|
1871 | architecture,
|
---|
1872 | driver->cversion);
|
---|
1873 | if (!new_dir) {
|
---|
1874 | *perr = WERR_NOMEM;
|
---|
1875 | goto err_exit;
|
---|
1876 | }
|
---|
1877 | new_dir = driver_unix_convert(conn,new_dir,&st);
|
---|
1878 | if (!new_dir) {
|
---|
1879 | *perr = WERR_NOMEM;
|
---|
1880 | goto err_exit;
|
---|
1881 | }
|
---|
1882 |
|
---|
1883 | create_directory(conn, NULL, new_dir);
|
---|
1884 |
|
---|
1885 | /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
|
---|
1886 | * listed for this driver which has already been moved, skip it (note:
|
---|
1887 | * drivers may list the same file name several times. Then check if the
|
---|
1888 | * file already exists in archi\cversion\, if so, check that the version
|
---|
1889 | * info (or time stamps if version info is unavailable) is newer (or the
|
---|
1890 | * date is later). If it is, move it to archi\cversion\filexxx.yyy.
|
---|
1891 | * Otherwise, delete the file.
|
---|
1892 | *
|
---|
1893 | * If a file is not moved to archi\cversion\ because of an error, all the
|
---|
1894 | * rest of the 'unmoved' driver files are removed from archi\. If one or
|
---|
1895 | * more of the driver's files was already moved to archi\cversion\, it
|
---|
1896 | * potentially leaves the driver in a partially updated state. Version
|
---|
1897 | * trauma will most likely occur if an client attempts to use any printer
|
---|
1898 | * bound to the driver. Perhaps a rewrite to make sure the moves can be
|
---|
1899 | * done is appropriate... later JRR
|
---|
1900 | */
|
---|
1901 |
|
---|
1902 | DEBUG(5,("Moving files now !\n"));
|
---|
1903 |
|
---|
1904 | if (driver->driverpath && strlen(driver->driverpath)) {
|
---|
1905 | new_name = talloc_asprintf(ctx,
|
---|
1906 | "%s/%s",
|
---|
1907 | architecture,
|
---|
1908 | driver->driverpath);
|
---|
1909 | if (!new_name) {
|
---|
1910 | *perr = WERR_NOMEM;
|
---|
1911 | goto err_exit;
|
---|
1912 | }
|
---|
1913 | old_name = talloc_asprintf(ctx,
|
---|
1914 | "%s/%s",
|
---|
1915 | new_dir,
|
---|
1916 | driver->driverpath);
|
---|
1917 | if (!old_name) {
|
---|
1918 | *perr = WERR_NOMEM;
|
---|
1919 | goto err_exit;
|
---|
1920 | }
|
---|
1921 |
|
---|
1922 | if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
|
---|
1923 | new_name = driver_unix_convert(conn,new_name,&st);
|
---|
1924 | if (!new_name) {
|
---|
1925 | *perr = WERR_NOMEM;
|
---|
1926 | goto err_exit;
|
---|
1927 | }
|
---|
1928 | if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
|
---|
1929 | OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
|
---|
1930 | DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
|
---|
1931 | new_name, old_name));
|
---|
1932 | *perr = WERR_ACCESS_DENIED;
|
---|
1933 | ver = -1;
|
---|
1934 | }
|
---|
1935 | }
|
---|
1936 | }
|
---|
1937 |
|
---|
1938 | if (driver->datafile && strlen(driver->datafile)) {
|
---|
1939 | if (!strequal(driver->datafile, driver->driverpath)) {
|
---|
1940 | new_name = talloc_asprintf(ctx,
|
---|
1941 | "%s/%s",
|
---|
1942 | architecture,
|
---|
1943 | driver->datafile);
|
---|
1944 | if (!new_name) {
|
---|
1945 | *perr = WERR_NOMEM;
|
---|
1946 | goto err_exit;
|
---|
1947 | }
|
---|
1948 | old_name = talloc_asprintf(ctx,
|
---|
1949 | "%s/%s",
|
---|
1950 | new_dir,
|
---|
1951 | driver->datafile);
|
---|
1952 | if (!old_name) {
|
---|
1953 | *perr = WERR_NOMEM;
|
---|
1954 | goto err_exit;
|
---|
1955 | }
|
---|
1956 | if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
|
---|
1957 | new_name = driver_unix_convert(conn,new_name,&st);
|
---|
1958 | if (!new_name) {
|
---|
1959 | *perr = WERR_NOMEM;
|
---|
1960 | goto err_exit;
|
---|
1961 | }
|
---|
1962 | if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
|
---|
1963 | OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
|
---|
1964 | DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
|
---|
1965 | new_name, old_name));
|
---|
1966 | *perr = WERR_ACCESS_DENIED;
|
---|
1967 | ver = -1;
|
---|
1968 | }
|
---|
1969 | }
|
---|
1970 | }
|
---|
1971 | }
|
---|
1972 |
|
---|
1973 | if (driver->configfile && strlen(driver->configfile)) {
|
---|
1974 | if (!strequal(driver->configfile, driver->driverpath) &&
|
---|
1975 | !strequal(driver->configfile, driver->datafile)) {
|
---|
1976 | new_name = talloc_asprintf(ctx,
|
---|
1977 | "%s/%s",
|
---|
1978 | architecture,
|
---|
1979 | driver->configfile);
|
---|
1980 | if (!new_name) {
|
---|
1981 | *perr = WERR_NOMEM;
|
---|
1982 | goto err_exit;
|
---|
1983 | }
|
---|
1984 | old_name = talloc_asprintf(ctx,
|
---|
1985 | "%s/%s",
|
---|
1986 | new_dir,
|
---|
1987 | driver->configfile);
|
---|
1988 | if (!old_name) {
|
---|
1989 | *perr = WERR_NOMEM;
|
---|
1990 | goto err_exit;
|
---|
1991 | }
|
---|
1992 | if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
|
---|
1993 | new_name = driver_unix_convert(conn,new_name,&st);
|
---|
1994 | if (!new_name) {
|
---|
1995 | *perr = WERR_NOMEM;
|
---|
1996 | goto err_exit;
|
---|
1997 | }
|
---|
1998 | if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
|
---|
1999 | OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
|
---|
2000 | DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
|
---|
2001 | new_name, old_name));
|
---|
2002 | *perr = WERR_ACCESS_DENIED;
|
---|
2003 | ver = -1;
|
---|
2004 | }
|
---|
2005 | }
|
---|
2006 | }
|
---|
2007 | }
|
---|
2008 |
|
---|
2009 | if (driver->helpfile && strlen(driver->helpfile)) {
|
---|
2010 | if (!strequal(driver->helpfile, driver->driverpath) &&
|
---|
2011 | !strequal(driver->helpfile, driver->datafile) &&
|
---|
2012 | !strequal(driver->helpfile, driver->configfile)) {
|
---|
2013 | new_name = talloc_asprintf(ctx,
|
---|
2014 | "%s/%s",
|
---|
2015 | architecture,
|
---|
2016 | driver->helpfile);
|
---|
2017 | if (!new_name) {
|
---|
2018 | *perr = WERR_NOMEM;
|
---|
2019 | goto err_exit;
|
---|
2020 | }
|
---|
2021 | old_name = talloc_asprintf(ctx,
|
---|
2022 | "%s/%s",
|
---|
2023 | new_dir,
|
---|
2024 | driver->helpfile);
|
---|
2025 | if (!old_name) {
|
---|
2026 | *perr = WERR_NOMEM;
|
---|
2027 | goto err_exit;
|
---|
2028 | }
|
---|
2029 | if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
|
---|
2030 | new_name = driver_unix_convert(conn,new_name,&st);
|
---|
2031 | if (!new_name) {
|
---|
2032 | *perr = WERR_NOMEM;
|
---|
2033 | goto err_exit;
|
---|
2034 | }
|
---|
2035 | if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
|
---|
2036 | OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
|
---|
2037 | DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
|
---|
2038 | new_name, old_name));
|
---|
2039 | *perr = WERR_ACCESS_DENIED;
|
---|
2040 | ver = -1;
|
---|
2041 | }
|
---|
2042 | }
|
---|
2043 | }
|
---|
2044 | }
|
---|
2045 |
|
---|
2046 | if (driver->dependentfiles) {
|
---|
2047 | for (i=0; *driver->dependentfiles[i]; i++) {
|
---|
2048 | if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
|
---|
2049 | !strequal(driver->dependentfiles[i], driver->datafile) &&
|
---|
2050 | !strequal(driver->dependentfiles[i], driver->configfile) &&
|
---|
2051 | !strequal(driver->dependentfiles[i], driver->helpfile)) {
|
---|
2052 | int j;
|
---|
2053 | for (j=0; j < i; j++) {
|
---|
2054 | if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
|
---|
2055 | goto NextDriver;
|
---|
2056 | }
|
---|
2057 | }
|
---|
2058 |
|
---|
2059 | new_name = talloc_asprintf(ctx,
|
---|
2060 | "%s/%s",
|
---|
2061 | architecture,
|
---|
2062 | driver->dependentfiles[i]);
|
---|
2063 | if (!new_name) {
|
---|
2064 | *perr = WERR_NOMEM;
|
---|
2065 | goto err_exit;
|
---|
2066 | }
|
---|
2067 | old_name = talloc_asprintf(ctx,
|
---|
2068 | "%s/%s",
|
---|
2069 | new_dir,
|
---|
2070 | driver->dependentfiles[i]);
|
---|
2071 | if (!old_name) {
|
---|
2072 | *perr = WERR_NOMEM;
|
---|
2073 | goto err_exit;
|
---|
2074 | }
|
---|
2075 | if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
|
---|
2076 | new_name = driver_unix_convert(conn,new_name,&st);
|
---|
2077 | if (!new_name) {
|
---|
2078 | *perr = WERR_NOMEM;
|
---|
2079 | goto err_exit;
|
---|
2080 | }
|
---|
2081 | if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
|
---|
2082 | OPENX_FILE_EXISTS_TRUNCATE|
|
---|
2083 | OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
|
---|
2084 | DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
|
---|
2085 | new_name, old_name));
|
---|
2086 | *perr = WERR_ACCESS_DENIED;
|
---|
2087 | ver = -1;
|
---|
2088 | }
|
---|
2089 | }
|
---|
2090 | }
|
---|
2091 | NextDriver: ;
|
---|
2092 | }
|
---|
2093 | }
|
---|
2094 |
|
---|
2095 | err_exit:
|
---|
2096 |
|
---|
2097 | close_cnum(conn, user->vuid);
|
---|
2098 | unbecome_user();
|
---|
2099 |
|
---|
2100 | if (W_ERROR_EQUAL(*perr, WERR_OK)) {
|
---|
2101 | return WERR_OK;
|
---|
2102 | }
|
---|
2103 | if (ver == -1) {
|
---|
2104 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
2105 | }
|
---|
2106 | return (*perr);
|
---|
2107 | }
|
---|
2108 |
|
---|
2109 | /****************************************************************************
|
---|
2110 | ****************************************************************************/
|
---|
2111 |
|
---|
2112 | static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
|
---|
2113 | {
|
---|
2114 | TALLOC_CTX *ctx = talloc_tos();
|
---|
2115 | int len, buflen;
|
---|
2116 | const char *architecture;
|
---|
2117 | char *directory = NULL;
|
---|
2118 | fstring temp_name;
|
---|
2119 | char *key = NULL;
|
---|
2120 | uint8 *buf;
|
---|
2121 | int i, ret;
|
---|
2122 | TDB_DATA dbuf;
|
---|
2123 |
|
---|
2124 | architecture = get_short_archi(driver->environment);
|
---|
2125 | if (!architecture) {
|
---|
2126 | return (uint32)-1;
|
---|
2127 | }
|
---|
2128 |
|
---|
2129 | /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
|
---|
2130 | * \\server is added in the rpc server layer.
|
---|
2131 | * It does make sense to NOT store the server's name in the printer TDB.
|
---|
2132 | */
|
---|
2133 |
|
---|
2134 | directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
|
---|
2135 | architecture, driver->cversion);
|
---|
2136 | if (!directory) {
|
---|
2137 | return (uint32)-1;
|
---|
2138 | }
|
---|
2139 |
|
---|
2140 | /* .inf files do not always list a file for each of the four standard files.
|
---|
2141 | * Don't prepend a path to a null filename, or client claims:
|
---|
2142 | * "The server on which the printer resides does not have a suitable
|
---|
2143 | * <printer driver name> printer driver installed. Click OK if you
|
---|
2144 | * wish to install the driver on your local machine."
|
---|
2145 | */
|
---|
2146 | if (strlen(driver->driverpath)) {
|
---|
2147 | fstrcpy(temp_name, driver->driverpath);
|
---|
2148 | slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
|
---|
2149 | }
|
---|
2150 |
|
---|
2151 | if (strlen(driver->datafile)) {
|
---|
2152 | fstrcpy(temp_name, driver->datafile);
|
---|
2153 | slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
|
---|
2154 | }
|
---|
2155 |
|
---|
2156 | if (strlen(driver->configfile)) {
|
---|
2157 | fstrcpy(temp_name, driver->configfile);
|
---|
2158 | slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
|
---|
2159 | }
|
---|
2160 |
|
---|
2161 | if (strlen(driver->helpfile)) {
|
---|
2162 | fstrcpy(temp_name, driver->helpfile);
|
---|
2163 | slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
|
---|
2164 | }
|
---|
2165 |
|
---|
2166 | if (driver->dependentfiles) {
|
---|
2167 | for (i=0; *driver->dependentfiles[i]; i++) {
|
---|
2168 | fstrcpy(temp_name, driver->dependentfiles[i]);
|
---|
2169 | slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
|
---|
2170 | }
|
---|
2171 | }
|
---|
2172 |
|
---|
2173 | key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
|
---|
2174 | architecture, driver->cversion, driver->name);
|
---|
2175 | if (!key) {
|
---|
2176 | return (uint32)-1;
|
---|
2177 | }
|
---|
2178 |
|
---|
2179 | DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
|
---|
2180 |
|
---|
2181 | buf = NULL;
|
---|
2182 | len = buflen = 0;
|
---|
2183 |
|
---|
2184 | again:
|
---|
2185 | len = 0;
|
---|
2186 | len += tdb_pack(buf+len, buflen-len, "dffffffff",
|
---|
2187 | driver->cversion,
|
---|
2188 | driver->name,
|
---|
2189 | driver->environment,
|
---|
2190 | driver->driverpath,
|
---|
2191 | driver->datafile,
|
---|
2192 | driver->configfile,
|
---|
2193 | driver->helpfile,
|
---|
2194 | driver->monitorname,
|
---|
2195 | driver->defaultdatatype);
|
---|
2196 |
|
---|
2197 | if (driver->dependentfiles) {
|
---|
2198 | for (i=0; *driver->dependentfiles[i]; i++) {
|
---|
2199 | len += tdb_pack(buf+len, buflen-len, "f",
|
---|
2200 | driver->dependentfiles[i]);
|
---|
2201 | }
|
---|
2202 | }
|
---|
2203 |
|
---|
2204 | if (len != buflen) {
|
---|
2205 | buf = (uint8 *)SMB_REALLOC(buf, len);
|
---|
2206 | if (!buf) {
|
---|
2207 | DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
|
---|
2208 | ret = -1;
|
---|
2209 | goto done;
|
---|
2210 | }
|
---|
2211 | buflen = len;
|
---|
2212 | goto again;
|
---|
2213 | }
|
---|
2214 |
|
---|
2215 | dbuf.dptr = buf;
|
---|
2216 | dbuf.dsize = len;
|
---|
2217 |
|
---|
2218 | ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
|
---|
2219 |
|
---|
2220 | done:
|
---|
2221 | if (ret)
|
---|
2222 | DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
|
---|
2223 |
|
---|
2224 | SAFE_FREE(buf);
|
---|
2225 | return ret;
|
---|
2226 | }
|
---|
2227 |
|
---|
2228 | /****************************************************************************
|
---|
2229 | ****************************************************************************/
|
---|
2230 | static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
|
---|
2231 | {
|
---|
2232 | NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
|
---|
2233 |
|
---|
2234 | ZERO_STRUCT(info3);
|
---|
2235 | info3.cversion = driver->version;
|
---|
2236 | fstrcpy(info3.name,driver->name);
|
---|
2237 | fstrcpy(info3.environment,driver->environment);
|
---|
2238 | fstrcpy(info3.driverpath,driver->driverpath);
|
---|
2239 | fstrcpy(info3.datafile,driver->datafile);
|
---|
2240 | fstrcpy(info3.configfile,driver->configfile);
|
---|
2241 | fstrcpy(info3.helpfile,driver->helpfile);
|
---|
2242 | fstrcpy(info3.monitorname,driver->monitorname);
|
---|
2243 | fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
|
---|
2244 | info3.dependentfiles = driver->dependentfiles;
|
---|
2245 |
|
---|
2246 | return add_a_printer_driver_3(&info3);
|
---|
2247 | }
|
---|
2248 |
|
---|
2249 |
|
---|
2250 | /****************************************************************************
|
---|
2251 | ****************************************************************************/
|
---|
2252 | static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
|
---|
2253 | {
|
---|
2254 | NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
|
---|
2255 |
|
---|
2256 | ZERO_STRUCT(info);
|
---|
2257 |
|
---|
2258 | fstrcpy(info.name, driver);
|
---|
2259 | fstrcpy(info.defaultdatatype, "RAW");
|
---|
2260 |
|
---|
2261 | fstrcpy(info.driverpath, "");
|
---|
2262 | fstrcpy(info.datafile, "");
|
---|
2263 | fstrcpy(info.configfile, "");
|
---|
2264 | fstrcpy(info.helpfile, "");
|
---|
2265 |
|
---|
2266 | if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
|
---|
2267 | return WERR_NOMEM;
|
---|
2268 |
|
---|
2269 | memset(info.dependentfiles, '\0', 2*sizeof(fstring));
|
---|
2270 | fstrcpy(info.dependentfiles[0], "");
|
---|
2271 |
|
---|
2272 | *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
|
---|
2273 | if (!*info_ptr) {
|
---|
2274 | SAFE_FREE(info.dependentfiles);
|
---|
2275 | return WERR_NOMEM;
|
---|
2276 | }
|
---|
2277 |
|
---|
2278 | return WERR_OK;
|
---|
2279 | }
|
---|
2280 |
|
---|
2281 | /****************************************************************************
|
---|
2282 | ****************************************************************************/
|
---|
2283 | static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
|
---|
2284 | {
|
---|
2285 | NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
|
---|
2286 | TDB_DATA dbuf;
|
---|
2287 | const char *architecture;
|
---|
2288 | int len = 0;
|
---|
2289 | int i;
|
---|
2290 | char *key = NULL;
|
---|
2291 |
|
---|
2292 | ZERO_STRUCT(driver);
|
---|
2293 |
|
---|
2294 | architecture = get_short_archi(arch);
|
---|
2295 | if ( !architecture ) {
|
---|
2296 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
2297 | }
|
---|
2298 |
|
---|
2299 | /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
|
---|
2300 |
|
---|
2301 | if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
|
---|
2302 | version = 0;
|
---|
2303 |
|
---|
2304 | DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
|
---|
2305 |
|
---|
2306 | if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
|
---|
2307 | architecture, version, drivername) < 0) {
|
---|
2308 | return WERR_NOMEM;
|
---|
2309 | }
|
---|
2310 |
|
---|
2311 | dbuf = tdb_fetch_bystring(tdb_drivers, key);
|
---|
2312 | if (!dbuf.dptr) {
|
---|
2313 | SAFE_FREE(key);
|
---|
2314 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
2315 | }
|
---|
2316 |
|
---|
2317 | len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
|
---|
2318 | &driver.cversion,
|
---|
2319 | driver.name,
|
---|
2320 | driver.environment,
|
---|
2321 | driver.driverpath,
|
---|
2322 | driver.datafile,
|
---|
2323 | driver.configfile,
|
---|
2324 | driver.helpfile,
|
---|
2325 | driver.monitorname,
|
---|
2326 | driver.defaultdatatype);
|
---|
2327 |
|
---|
2328 | i=0;
|
---|
2329 | while (len < dbuf.dsize) {
|
---|
2330 | driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
|
---|
2331 | if ( !driver.dependentfiles ) {
|
---|
2332 | DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
|
---|
2333 | break;
|
---|
2334 | }
|
---|
2335 |
|
---|
2336 | len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
|
---|
2337 | &driver.dependentfiles[i]);
|
---|
2338 | i++;
|
---|
2339 | }
|
---|
2340 |
|
---|
2341 | if ( driver.dependentfiles )
|
---|
2342 | fstrcpy( driver.dependentfiles[i], "" );
|
---|
2343 |
|
---|
2344 | SAFE_FREE(dbuf.dptr);
|
---|
2345 | SAFE_FREE(key);
|
---|
2346 |
|
---|
2347 | if (len != dbuf.dsize) {
|
---|
2348 | SAFE_FREE(driver.dependentfiles);
|
---|
2349 |
|
---|
2350 | return get_a_printer_driver_3_default(info_ptr, drivername, arch);
|
---|
2351 | }
|
---|
2352 |
|
---|
2353 | *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
|
---|
2354 | if (!*info_ptr) {
|
---|
2355 | SAFE_FREE(driver.dependentfiles);
|
---|
2356 | return WERR_NOMEM;
|
---|
2357 | }
|
---|
2358 |
|
---|
2359 | return WERR_OK;
|
---|
2360 | }
|
---|
2361 |
|
---|
2362 | /****************************************************************************
|
---|
2363 | Debugging function, dump at level 6 the struct in the logs.
|
---|
2364 | ****************************************************************************/
|
---|
2365 |
|
---|
2366 | static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
|
---|
2367 | {
|
---|
2368 | uint32 result;
|
---|
2369 | NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
|
---|
2370 | int i;
|
---|
2371 |
|
---|
2372 | DEBUG(20,("Dumping printer driver at level [%d]\n", level));
|
---|
2373 |
|
---|
2374 | switch (level)
|
---|
2375 | {
|
---|
2376 | case 3:
|
---|
2377 | {
|
---|
2378 | if (driver.info_3 == NULL)
|
---|
2379 | result=5;
|
---|
2380 | else {
|
---|
2381 | info3=driver.info_3;
|
---|
2382 |
|
---|
2383 | DEBUGADD(20,("version:[%d]\n", info3->cversion));
|
---|
2384 | DEBUGADD(20,("name:[%s]\n", info3->name));
|
---|
2385 | DEBUGADD(20,("environment:[%s]\n", info3->environment));
|
---|
2386 | DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
|
---|
2387 | DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
|
---|
2388 | DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
|
---|
2389 | DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
|
---|
2390 | DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
|
---|
2391 | DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
|
---|
2392 |
|
---|
2393 | for (i=0; info3->dependentfiles &&
|
---|
2394 | *info3->dependentfiles[i]; i++) {
|
---|
2395 | DEBUGADD(20,("dependentfile:[%s]\n",
|
---|
2396 | info3->dependentfiles[i]));
|
---|
2397 | }
|
---|
2398 | result=0;
|
---|
2399 | }
|
---|
2400 | break;
|
---|
2401 | }
|
---|
2402 | default:
|
---|
2403 | DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
|
---|
2404 | result=1;
|
---|
2405 | break;
|
---|
2406 | }
|
---|
2407 |
|
---|
2408 | return result;
|
---|
2409 | }
|
---|
2410 |
|
---|
2411 | /****************************************************************************
|
---|
2412 | ****************************************************************************/
|
---|
2413 | int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
|
---|
2414 | {
|
---|
2415 | int len = 0;
|
---|
2416 |
|
---|
2417 | len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
|
---|
2418 |
|
---|
2419 | if (!nt_devmode)
|
---|
2420 | return len;
|
---|
2421 |
|
---|
2422 | len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
|
---|
2423 | nt_devmode->devicename,
|
---|
2424 | nt_devmode->formname,
|
---|
2425 |
|
---|
2426 | nt_devmode->specversion,
|
---|
2427 | nt_devmode->driverversion,
|
---|
2428 | nt_devmode->size,
|
---|
2429 | nt_devmode->driverextra,
|
---|
2430 | nt_devmode->orientation,
|
---|
2431 | nt_devmode->papersize,
|
---|
2432 | nt_devmode->paperlength,
|
---|
2433 | nt_devmode->paperwidth,
|
---|
2434 | nt_devmode->scale,
|
---|
2435 | nt_devmode->copies,
|
---|
2436 | nt_devmode->defaultsource,
|
---|
2437 | nt_devmode->printquality,
|
---|
2438 | nt_devmode->color,
|
---|
2439 | nt_devmode->duplex,
|
---|
2440 | nt_devmode->yresolution,
|
---|
2441 | nt_devmode->ttoption,
|
---|
2442 | nt_devmode->collate,
|
---|
2443 | nt_devmode->logpixels,
|
---|
2444 |
|
---|
2445 | nt_devmode->fields,
|
---|
2446 | nt_devmode->bitsperpel,
|
---|
2447 | nt_devmode->pelswidth,
|
---|
2448 | nt_devmode->pelsheight,
|
---|
2449 | nt_devmode->displayflags,
|
---|
2450 | nt_devmode->displayfrequency,
|
---|
2451 | nt_devmode->icmmethod,
|
---|
2452 | nt_devmode->icmintent,
|
---|
2453 | nt_devmode->mediatype,
|
---|
2454 | nt_devmode->dithertype,
|
---|
2455 | nt_devmode->reserved1,
|
---|
2456 | nt_devmode->reserved2,
|
---|
2457 | nt_devmode->panningwidth,
|
---|
2458 | nt_devmode->panningheight,
|
---|
2459 | nt_devmode->nt_dev_private);
|
---|
2460 |
|
---|
2461 | if (nt_devmode->nt_dev_private) {
|
---|
2462 | len += tdb_pack(buf+len, buflen-len, "B",
|
---|
2463 | nt_devmode->driverextra,
|
---|
2464 | nt_devmode->nt_dev_private);
|
---|
2465 | }
|
---|
2466 |
|
---|
2467 | DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
|
---|
2468 |
|
---|
2469 | return len;
|
---|
2470 | }
|
---|
2471 |
|
---|
2472 | /****************************************************************************
|
---|
2473 | Pack all values in all printer keys
|
---|
2474 | ***************************************************************************/
|
---|
2475 |
|
---|
2476 | static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
|
---|
2477 | {
|
---|
2478 | int len = 0;
|
---|
2479 | int i, j;
|
---|
2480 | REGISTRY_VALUE *val;
|
---|
2481 | REGVAL_CTR *val_ctr;
|
---|
2482 | char *path = NULL;
|
---|
2483 | int num_values;
|
---|
2484 |
|
---|
2485 | if ( !data )
|
---|
2486 | return 0;
|
---|
2487 |
|
---|
2488 | /* loop over all keys */
|
---|
2489 |
|
---|
2490 | for ( i=0; i<data->num_keys; i++ ) {
|
---|
2491 | val_ctr = data->keys[i].values;
|
---|
2492 | num_values = regval_ctr_numvals( val_ctr );
|
---|
2493 |
|
---|
2494 | /* pack the keyname followed by a empty value */
|
---|
2495 |
|
---|
2496 | len += tdb_pack(buf+len, buflen-len, "pPdB",
|
---|
2497 | &data->keys[i].name,
|
---|
2498 | data->keys[i].name,
|
---|
2499 | REG_NONE,
|
---|
2500 | 0,
|
---|
2501 | NULL);
|
---|
2502 |
|
---|
2503 | /* now loop over all values */
|
---|
2504 |
|
---|
2505 | for ( j=0; j<num_values; j++ ) {
|
---|
2506 | /* pathname should be stored as <key>\<value> */
|
---|
2507 |
|
---|
2508 | val = regval_ctr_specific_value( val_ctr, j );
|
---|
2509 | if (asprintf(&path, "%s\\%s",
|
---|
2510 | data->keys[i].name,
|
---|
2511 | regval_name(val)) < 0) {
|
---|
2512 | return -1;
|
---|
2513 | }
|
---|
2514 |
|
---|
2515 | len += tdb_pack(buf+len, buflen-len, "pPdB",
|
---|
2516 | val,
|
---|
2517 | path,
|
---|
2518 | regval_type(val),
|
---|
2519 | regval_size(val),
|
---|
2520 | regval_data_p(val) );
|
---|
2521 |
|
---|
2522 | DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
|
---|
2523 | SAFE_FREE(path);
|
---|
2524 | }
|
---|
2525 |
|
---|
2526 | }
|
---|
2527 |
|
---|
2528 | /* terminator */
|
---|
2529 |
|
---|
2530 | len += tdb_pack(buf+len, buflen-len, "p", NULL);
|
---|
2531 |
|
---|
2532 | return len;
|
---|
2533 | }
|
---|
2534 |
|
---|
2535 |
|
---|
2536 | /****************************************************************************
|
---|
2537 | Delete a printer - this just deletes the printer info file, any open
|
---|
2538 | handles are not affected.
|
---|
2539 | ****************************************************************************/
|
---|
2540 |
|
---|
2541 | uint32 del_a_printer(const char *sharename)
|
---|
2542 | {
|
---|
2543 | TDB_DATA kbuf;
|
---|
2544 | char *printdb_path = NULL;
|
---|
2545 | TALLOC_CTX *ctx = talloc_tos();
|
---|
2546 |
|
---|
2547 | kbuf = make_printer_tdbkey(ctx, sharename);
|
---|
2548 | tdb_delete(tdb_printers, kbuf);
|
---|
2549 |
|
---|
2550 | kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
|
---|
2551 | tdb_delete(tdb_printers, kbuf);
|
---|
2552 |
|
---|
2553 | close_all_print_db();
|
---|
2554 |
|
---|
2555 | if (geteuid() == 0) {
|
---|
2556 | if (asprintf(&printdb_path, "%s%s.tdb",
|
---|
2557 | lock_path("printing/"),
|
---|
2558 | sharename) < 0) {
|
---|
2559 | return (uint32)-1;
|
---|
2560 | }
|
---|
2561 | unlink(printdb_path);
|
---|
2562 | SAFE_FREE(printdb_path);
|
---|
2563 | }
|
---|
2564 |
|
---|
2565 | return 0;
|
---|
2566 | }
|
---|
2567 |
|
---|
2568 | /****************************************************************************
|
---|
2569 | ****************************************************************************/
|
---|
2570 | static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
|
---|
2571 | {
|
---|
2572 | uint8 *buf;
|
---|
2573 | int buflen, len;
|
---|
2574 | int retlen;
|
---|
2575 | WERROR ret;
|
---|
2576 | TDB_DATA kbuf, dbuf;
|
---|
2577 |
|
---|
2578 | /*
|
---|
2579 | * in addprinter: no servername and the printer is the name
|
---|
2580 | * in setprinter: servername is \\server
|
---|
2581 | * and printer is \\server\\printer
|
---|
2582 | *
|
---|
2583 | * Samba manages only local printers.
|
---|
2584 | * we currently don't support things like i
|
---|
2585 | * path=\\other_server\printer
|
---|
2586 | *
|
---|
2587 | * We only store the printername, not \\server\printername
|
---|
2588 | */
|
---|
2589 |
|
---|
2590 | if ( info->servername[0] != '\0' ) {
|
---|
2591 | trim_string(info->printername, info->servername, NULL);
|
---|
2592 | trim_char(info->printername, '\\', '\0');
|
---|
2593 | info->servername[0]='\0';
|
---|
2594 | }
|
---|
2595 |
|
---|
2596 | /*
|
---|
2597 | * JFM: one day I'll forget.
|
---|
2598 | * below that's info->portname because that's the SAMBA sharename
|
---|
2599 | * and I made NT 'thinks' it's the portname
|
---|
2600 | * the info->sharename is the thing you can name when you add a printer
|
---|
2601 | * that's the short-name when you create shared printer for 95/98
|
---|
2602 | * So I've made a limitation in SAMBA: you can only have 1 printer model
|
---|
2603 | * behind a SAMBA share.
|
---|
2604 | */
|
---|
2605 |
|
---|
2606 | buf = NULL;
|
---|
2607 | buflen = 0;
|
---|
2608 |
|
---|
2609 | again:
|
---|
2610 | len = 0;
|
---|
2611 | len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
|
---|
2612 | info->attributes,
|
---|
2613 | info->priority,
|
---|
2614 | info->default_priority,
|
---|
2615 | info->starttime,
|
---|
2616 | info->untiltime,
|
---|
2617 | info->status,
|
---|
2618 | info->cjobs,
|
---|
2619 | info->averageppm,
|
---|
2620 | info->changeid,
|
---|
2621 | info->c_setprinter,
|
---|
2622 | info->setuptime,
|
---|
2623 | info->servername,
|
---|
2624 | info->printername,
|
---|
2625 | info->sharename,
|
---|
2626 | info->portname,
|
---|
2627 | info->drivername,
|
---|
2628 | info->comment,
|
---|
2629 | info->location,
|
---|
2630 | info->sepfile,
|
---|
2631 | info->printprocessor,
|
---|
2632 | info->datatype,
|
---|
2633 | info->parameters);
|
---|
2634 |
|
---|
2635 | len += pack_devicemode(info->devmode, buf+len, buflen-len);
|
---|
2636 | retlen = pack_values( info->data, buf+len, buflen-len );
|
---|
2637 | if (retlen == -1) {
|
---|
2638 | ret = WERR_NOMEM;
|
---|
2639 | goto done;
|
---|
2640 | }
|
---|
2641 | len += retlen;
|
---|
2642 |
|
---|
2643 | if (buflen != len) {
|
---|
2644 | buf = (uint8 *)SMB_REALLOC(buf, len);
|
---|
2645 | if (!buf) {
|
---|
2646 | DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
|
---|
2647 | ret = WERR_NOMEM;
|
---|
2648 | goto done;
|
---|
2649 | }
|
---|
2650 | buflen = len;
|
---|
2651 | goto again;
|
---|
2652 | }
|
---|
2653 |
|
---|
2654 | kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
|
---|
2655 |
|
---|
2656 | dbuf.dptr = buf;
|
---|
2657 | dbuf.dsize = len;
|
---|
2658 |
|
---|
2659 | ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
|
---|
2660 |
|
---|
2661 | done:
|
---|
2662 | if (!W_ERROR_IS_OK(ret))
|
---|
2663 | DEBUG(8, ("error updating printer to tdb on disk\n"));
|
---|
2664 |
|
---|
2665 | SAFE_FREE(buf);
|
---|
2666 |
|
---|
2667 | DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
|
---|
2668 | info->sharename, info->drivername, info->portname, len));
|
---|
2669 |
|
---|
2670 | return ret;
|
---|
2671 | }
|
---|
2672 |
|
---|
2673 |
|
---|
2674 | /****************************************************************************
|
---|
2675 | Malloc and return an NT devicemode.
|
---|
2676 | ****************************************************************************/
|
---|
2677 |
|
---|
2678 | NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
|
---|
2679 | {
|
---|
2680 |
|
---|
2681 | char adevice[MAXDEVICENAME];
|
---|
2682 | NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
|
---|
2683 |
|
---|
2684 | if (nt_devmode == NULL) {
|
---|
2685 | DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
|
---|
2686 | return NULL;
|
---|
2687 | }
|
---|
2688 |
|
---|
2689 | ZERO_STRUCTP(nt_devmode);
|
---|
2690 |
|
---|
2691 | slprintf(adevice, sizeof(adevice), "%s", default_devicename);
|
---|
2692 | fstrcpy(nt_devmode->devicename, adevice);
|
---|
2693 |
|
---|
2694 | fstrcpy(nt_devmode->formname, "Letter");
|
---|
2695 |
|
---|
2696 | nt_devmode->specversion = 0x0401;
|
---|
2697 | nt_devmode->driverversion = 0x0400;
|
---|
2698 | nt_devmode->size = 0x00DC;
|
---|
2699 | nt_devmode->driverextra = 0x0000;
|
---|
2700 | nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
|
---|
2701 | DEFAULTSOURCE | COPIES | SCALE |
|
---|
2702 | PAPERSIZE | ORIENTATION;
|
---|
2703 | nt_devmode->orientation = 1;
|
---|
2704 | nt_devmode->papersize = PAPER_LETTER;
|
---|
2705 | nt_devmode->paperlength = 0;
|
---|
2706 | nt_devmode->paperwidth = 0;
|
---|
2707 | nt_devmode->scale = 0x64;
|
---|
2708 | nt_devmode->copies = 1;
|
---|
2709 | nt_devmode->defaultsource = BIN_FORMSOURCE;
|
---|
2710 | nt_devmode->printquality = RES_HIGH; /* 0x0258 */
|
---|
2711 | nt_devmode->color = COLOR_MONOCHROME;
|
---|
2712 | nt_devmode->duplex = DUP_SIMPLEX;
|
---|
2713 | nt_devmode->yresolution = 0;
|
---|
2714 | nt_devmode->ttoption = TT_SUBDEV;
|
---|
2715 | nt_devmode->collate = COLLATE_FALSE;
|
---|
2716 | nt_devmode->icmmethod = 0;
|
---|
2717 | nt_devmode->icmintent = 0;
|
---|
2718 | nt_devmode->mediatype = 0;
|
---|
2719 | nt_devmode->dithertype = 0;
|
---|
2720 |
|
---|
2721 | /* non utilisés par un driver d'imprimante */
|
---|
2722 | nt_devmode->logpixels = 0;
|
---|
2723 | nt_devmode->bitsperpel = 0;
|
---|
2724 | nt_devmode->pelswidth = 0;
|
---|
2725 | nt_devmode->pelsheight = 0;
|
---|
2726 | nt_devmode->displayflags = 0;
|
---|
2727 | nt_devmode->displayfrequency = 0;
|
---|
2728 | nt_devmode->reserved1 = 0;
|
---|
2729 | nt_devmode->reserved2 = 0;
|
---|
2730 | nt_devmode->panningwidth = 0;
|
---|
2731 | nt_devmode->panningheight = 0;
|
---|
2732 |
|
---|
2733 | nt_devmode->nt_dev_private = NULL;
|
---|
2734 | return nt_devmode;
|
---|
2735 | }
|
---|
2736 |
|
---|
2737 | /****************************************************************************
|
---|
2738 | Deepcopy an NT devicemode.
|
---|
2739 | ****************************************************************************/
|
---|
2740 |
|
---|
2741 | NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
|
---|
2742 | {
|
---|
2743 | NT_DEVICEMODE *new_nt_devicemode = NULL;
|
---|
2744 |
|
---|
2745 | if ( !nt_devicemode )
|
---|
2746 | return NULL;
|
---|
2747 |
|
---|
2748 | if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
|
---|
2749 | DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
|
---|
2750 | return NULL;
|
---|
2751 | }
|
---|
2752 |
|
---|
2753 | new_nt_devicemode->nt_dev_private = NULL;
|
---|
2754 | if (nt_devicemode->nt_dev_private != NULL) {
|
---|
2755 | if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
|
---|
2756 | SAFE_FREE(new_nt_devicemode);
|
---|
2757 | DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
|
---|
2758 | return NULL;
|
---|
2759 | }
|
---|
2760 | }
|
---|
2761 |
|
---|
2762 | return new_nt_devicemode;
|
---|
2763 | }
|
---|
2764 |
|
---|
2765 | /****************************************************************************
|
---|
2766 | Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
|
---|
2767 | ****************************************************************************/
|
---|
2768 |
|
---|
2769 | void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
|
---|
2770 | {
|
---|
2771 | NT_DEVICEMODE *nt_devmode = *devmode_ptr;
|
---|
2772 |
|
---|
2773 | if(nt_devmode == NULL)
|
---|
2774 | return;
|
---|
2775 |
|
---|
2776 | DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
|
---|
2777 |
|
---|
2778 | SAFE_FREE(nt_devmode->nt_dev_private);
|
---|
2779 | SAFE_FREE(*devmode_ptr);
|
---|
2780 | }
|
---|
2781 |
|
---|
2782 | /****************************************************************************
|
---|
2783 | Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
|
---|
2784 | ****************************************************************************/
|
---|
2785 |
|
---|
2786 | static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
|
---|
2787 | {
|
---|
2788 | NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
|
---|
2789 |
|
---|
2790 | if ( !info )
|
---|
2791 | return;
|
---|
2792 |
|
---|
2793 | free_nt_devicemode(&info->devmode);
|
---|
2794 |
|
---|
2795 | TALLOC_FREE( *info_ptr );
|
---|
2796 | }
|
---|
2797 |
|
---|
2798 |
|
---|
2799 | /****************************************************************************
|
---|
2800 | ****************************************************************************/
|
---|
2801 | int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
|
---|
2802 | {
|
---|
2803 | int len = 0;
|
---|
2804 | int extra_len = 0;
|
---|
2805 | NT_DEVICEMODE devmode;
|
---|
2806 |
|
---|
2807 | ZERO_STRUCT(devmode);
|
---|
2808 |
|
---|
2809 | len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
|
---|
2810 |
|
---|
2811 | if (!*nt_devmode) return len;
|
---|
2812 |
|
---|
2813 | len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
|
---|
2814 | devmode.devicename,
|
---|
2815 | devmode.formname,
|
---|
2816 |
|
---|
2817 | &devmode.specversion,
|
---|
2818 | &devmode.driverversion,
|
---|
2819 | &devmode.size,
|
---|
2820 | &devmode.driverextra,
|
---|
2821 | &devmode.orientation,
|
---|
2822 | &devmode.papersize,
|
---|
2823 | &devmode.paperlength,
|
---|
2824 | &devmode.paperwidth,
|
---|
2825 | &devmode.scale,
|
---|
2826 | &devmode.copies,
|
---|
2827 | &devmode.defaultsource,
|
---|
2828 | &devmode.printquality,
|
---|
2829 | &devmode.color,
|
---|
2830 | &devmode.duplex,
|
---|
2831 | &devmode.yresolution,
|
---|
2832 | &devmode.ttoption,
|
---|
2833 | &devmode.collate,
|
---|
2834 | &devmode.logpixels,
|
---|
2835 |
|
---|
2836 | &devmode.fields,
|
---|
2837 | &devmode.bitsperpel,
|
---|
2838 | &devmode.pelswidth,
|
---|
2839 | &devmode.pelsheight,
|
---|
2840 | &devmode.displayflags,
|
---|
2841 | &devmode.displayfrequency,
|
---|
2842 | &devmode.icmmethod,
|
---|
2843 | &devmode.icmintent,
|
---|
2844 | &devmode.mediatype,
|
---|
2845 | &devmode.dithertype,
|
---|
2846 | &devmode.reserved1,
|
---|
2847 | &devmode.reserved2,
|
---|
2848 | &devmode.panningwidth,
|
---|
2849 | &devmode.panningheight,
|
---|
2850 | &devmode.nt_dev_private);
|
---|
2851 |
|
---|
2852 | if (devmode.nt_dev_private) {
|
---|
2853 | /* the len in tdb_unpack is an int value and
|
---|
2854 | * devmode.driverextra is only a short
|
---|
2855 | */
|
---|
2856 | len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
|
---|
2857 | devmode.driverextra=(uint16)extra_len;
|
---|
2858 |
|
---|
2859 | /* check to catch an invalid TDB entry so we don't segfault */
|
---|
2860 | if (devmode.driverextra == 0) {
|
---|
2861 | devmode.nt_dev_private = NULL;
|
---|
2862 | }
|
---|
2863 | }
|
---|
2864 |
|
---|
2865 | *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
|
---|
2866 | if (!*nt_devmode) {
|
---|
2867 | SAFE_FREE(devmode.nt_dev_private);
|
---|
2868 | return -1;
|
---|
2869 | }
|
---|
2870 |
|
---|
2871 | DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
|
---|
2872 | if (devmode.nt_dev_private)
|
---|
2873 | DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
|
---|
2874 |
|
---|
2875 | return len;
|
---|
2876 | }
|
---|
2877 |
|
---|
2878 | /****************************************************************************
|
---|
2879 | Allocate and initialize a new slot.
|
---|
2880 | ***************************************************************************/
|
---|
2881 |
|
---|
2882 | int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
|
---|
2883 | {
|
---|
2884 | NT_PRINTER_KEY *d;
|
---|
2885 | int key_index;
|
---|
2886 |
|
---|
2887 | if ( !name || !data )
|
---|
2888 | return -1;
|
---|
2889 |
|
---|
2890 | /* allocate another slot in the NT_PRINTER_KEY array */
|
---|
2891 |
|
---|
2892 | if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
|
---|
2893 | DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
|
---|
2894 | return -1;
|
---|
2895 | }
|
---|
2896 |
|
---|
2897 | data->keys = d;
|
---|
2898 |
|
---|
2899 | key_index = data->num_keys;
|
---|
2900 |
|
---|
2901 | /* initialze new key */
|
---|
2902 |
|
---|
2903 | data->keys[key_index].name = talloc_strdup( data, name );
|
---|
2904 |
|
---|
2905 | if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
|
---|
2906 | return -1;
|
---|
2907 |
|
---|
2908 | data->num_keys++;
|
---|
2909 |
|
---|
2910 | DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
|
---|
2911 |
|
---|
2912 | return key_index;
|
---|
2913 | }
|
---|
2914 |
|
---|
2915 | /****************************************************************************
|
---|
2916 | search for a registry key name in the existing printer data
|
---|
2917 | ***************************************************************************/
|
---|
2918 |
|
---|
2919 | int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
|
---|
2920 | {
|
---|
2921 | int i;
|
---|
2922 |
|
---|
2923 | for ( i=0; i<data->num_keys; i++ ) {
|
---|
2924 | if ( strequal( data->keys[i].name, name ) ) {
|
---|
2925 |
|
---|
2926 | /* cleanup memory */
|
---|
2927 |
|
---|
2928 | TALLOC_FREE( data->keys[i].name );
|
---|
2929 | TALLOC_FREE( data->keys[i].values );
|
---|
2930 |
|
---|
2931 | /* if not the end of the array, move remaining elements down one slot */
|
---|
2932 |
|
---|
2933 | data->num_keys--;
|
---|
2934 | if ( data->num_keys && (i < data->num_keys) )
|
---|
2935 | memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
|
---|
2936 |
|
---|
2937 | break;
|
---|
2938 | }
|
---|
2939 | }
|
---|
2940 |
|
---|
2941 |
|
---|
2942 | return data->num_keys;
|
---|
2943 | }
|
---|
2944 |
|
---|
2945 | /****************************************************************************
|
---|
2946 | search for a registry key name in the existing printer data
|
---|
2947 | ***************************************************************************/
|
---|
2948 |
|
---|
2949 | int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
|
---|
2950 | {
|
---|
2951 | int key_index = -1;
|
---|
2952 | int i;
|
---|
2953 |
|
---|
2954 | if ( !data || !name )
|
---|
2955 | return -1;
|
---|
2956 |
|
---|
2957 | DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
|
---|
2958 |
|
---|
2959 | /* loop over all existing keys */
|
---|
2960 |
|
---|
2961 | for ( i=0; i<data->num_keys; i++ ) {
|
---|
2962 | if ( strequal(data->keys[i].name, name) ) {
|
---|
2963 | DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
|
---|
2964 | key_index = i;
|
---|
2965 | break;
|
---|
2966 |
|
---|
2967 | }
|
---|
2968 | }
|
---|
2969 |
|
---|
2970 | return key_index;
|
---|
2971 | }
|
---|
2972 |
|
---|
2973 | /****************************************************************************
|
---|
2974 | ***************************************************************************/
|
---|
2975 |
|
---|
2976 | int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
|
---|
2977 | {
|
---|
2978 | int i, j;
|
---|
2979 | int key_len;
|
---|
2980 | int num_subkeys = 0;
|
---|
2981 | char *p;
|
---|
2982 | fstring *subkeys_ptr = NULL;
|
---|
2983 | fstring subkeyname;
|
---|
2984 |
|
---|
2985 | *subkeys = NULL;
|
---|
2986 |
|
---|
2987 | if ( !data )
|
---|
2988 | return 0;
|
---|
2989 |
|
---|
2990 | if ( !key )
|
---|
2991 | return -1;
|
---|
2992 |
|
---|
2993 | /* special case of asking for the top level printer data registry key names */
|
---|
2994 |
|
---|
2995 | if ( strlen(key) == 0 ) {
|
---|
2996 | for ( i=0; i<data->num_keys; i++ ) {
|
---|
2997 |
|
---|
2998 | /* found a match, so allocate space and copy the name */
|
---|
2999 |
|
---|
3000 | if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
|
---|
3001 | DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
|
---|
3002 | num_subkeys+1));
|
---|
3003 | return -1;
|
---|
3004 | }
|
---|
3005 |
|
---|
3006 | fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
|
---|
3007 | num_subkeys++;
|
---|
3008 | }
|
---|
3009 |
|
---|
3010 | goto done;
|
---|
3011 | }
|
---|
3012 |
|
---|
3013 | /* asking for the subkeys of some key */
|
---|
3014 | /* subkey paths are stored in the key name using '\' as the delimiter */
|
---|
3015 |
|
---|
3016 | for ( i=0; i<data->num_keys; i++ ) {
|
---|
3017 | if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
|
---|
3018 |
|
---|
3019 | /* if we found the exact key, then break */
|
---|
3020 | key_len = strlen( key );
|
---|
3021 | if ( strlen(data->keys[i].name) == key_len )
|
---|
3022 | break;
|
---|
3023 |
|
---|
3024 | /* get subkey path */
|
---|
3025 |
|
---|
3026 | p = data->keys[i].name + key_len;
|
---|
3027 | if ( *p == '\\' )
|
---|
3028 | p++;
|
---|
3029 | fstrcpy( subkeyname, p );
|
---|
3030 | if ( (p = strchr( subkeyname, '\\' )) )
|
---|
3031 | *p = '\0';
|
---|
3032 |
|
---|
3033 | /* don't add a key more than once */
|
---|
3034 |
|
---|
3035 | for ( j=0; j<num_subkeys; j++ ) {
|
---|
3036 | if ( strequal( subkeys_ptr[j], subkeyname ) )
|
---|
3037 | break;
|
---|
3038 | }
|
---|
3039 |
|
---|
3040 | if ( j != num_subkeys )
|
---|
3041 | continue;
|
---|
3042 |
|
---|
3043 | /* found a match, so allocate space and copy the name */
|
---|
3044 |
|
---|
3045 | if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
|
---|
3046 | DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
|
---|
3047 | num_subkeys+1));
|
---|
3048 | return 0;
|
---|
3049 | }
|
---|
3050 |
|
---|
3051 | fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
|
---|
3052 | num_subkeys++;
|
---|
3053 | }
|
---|
3054 |
|
---|
3055 | }
|
---|
3056 |
|
---|
3057 | /* return error if the key was not found */
|
---|
3058 |
|
---|
3059 | if ( i == data->num_keys ) {
|
---|
3060 | SAFE_FREE(subkeys_ptr);
|
---|
3061 | return -1;
|
---|
3062 | }
|
---|
3063 |
|
---|
3064 | done:
|
---|
3065 | /* tag off the end */
|
---|
3066 |
|
---|
3067 | if (num_subkeys)
|
---|
3068 | fstrcpy(subkeys_ptr[num_subkeys], "" );
|
---|
3069 |
|
---|
3070 | *subkeys = subkeys_ptr;
|
---|
3071 |
|
---|
3072 | return num_subkeys;
|
---|
3073 | }
|
---|
3074 |
|
---|
3075 | #ifdef HAVE_ADS
|
---|
3076 | static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
|
---|
3077 | const char *sz)
|
---|
3078 | {
|
---|
3079 | smb_ucs2_t conv_str[1024];
|
---|
3080 | size_t str_size;
|
---|
3081 |
|
---|
3082 | regval_ctr_delvalue(ctr, val_name);
|
---|
3083 | str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
|
---|
3084 | STR_TERMINATE | STR_NOALIGN);
|
---|
3085 | regval_ctr_addvalue(ctr, val_name, REG_SZ,
|
---|
3086 | (char *) conv_str, str_size);
|
---|
3087 | }
|
---|
3088 |
|
---|
3089 | static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
|
---|
3090 | uint32 dword)
|
---|
3091 | {
|
---|
3092 | regval_ctr_delvalue(ctr, val_name);
|
---|
3093 | regval_ctr_addvalue(ctr, val_name, REG_DWORD,
|
---|
3094 | (char *) &dword, sizeof(dword));
|
---|
3095 | }
|
---|
3096 |
|
---|
3097 | static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
|
---|
3098 | bool b)
|
---|
3099 | {
|
---|
3100 | uint8 bin_bool = (b ? 1 : 0);
|
---|
3101 | regval_ctr_delvalue(ctr, val_name);
|
---|
3102 | regval_ctr_addvalue(ctr, val_name, REG_BINARY,
|
---|
3103 | (char *) &bin_bool, sizeof(bin_bool));
|
---|
3104 | }
|
---|
3105 |
|
---|
3106 | static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
|
---|
3107 | const char *multi_sz)
|
---|
3108 | {
|
---|
3109 | smb_ucs2_t *conv_strs = NULL;
|
---|
3110 | size_t str_size;
|
---|
3111 |
|
---|
3112 | /* a multi-sz has to have a null string terminator, i.e., the last
|
---|
3113 | string must be followed by two nulls */
|
---|
3114 | str_size = strlen(multi_sz) + 2;
|
---|
3115 | conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
|
---|
3116 | if (!conv_strs) {
|
---|
3117 | return;
|
---|
3118 | }
|
---|
3119 |
|
---|
3120 | /* Change to byte units. */
|
---|
3121 | str_size *= sizeof(smb_ucs2_t);
|
---|
3122 | push_ucs2(NULL, conv_strs, multi_sz, str_size,
|
---|
3123 | STR_TERMINATE | STR_NOALIGN);
|
---|
3124 |
|
---|
3125 | regval_ctr_delvalue(ctr, val_name);
|
---|
3126 | regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
|
---|
3127 | (char *) conv_strs, str_size);
|
---|
3128 | safe_free(conv_strs);
|
---|
3129 |
|
---|
3130 | }
|
---|
3131 |
|
---|
3132 | /****************************************************************************
|
---|
3133 | * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
|
---|
3134 | *
|
---|
3135 | * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
|
---|
3136 | * @return bool indicating success or failure
|
---|
3137 | ***************************************************************************/
|
---|
3138 |
|
---|
3139 | static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
|
---|
3140 | {
|
---|
3141 | REGVAL_CTR *ctr = NULL;
|
---|
3142 | fstring longname;
|
---|
3143 | const char *dnssuffix;
|
---|
3144 | char *allocated_string = NULL;
|
---|
3145 | const char *ascii_str;
|
---|
3146 | int i;
|
---|
3147 |
|
---|
3148 | if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
|
---|
3149 | i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
|
---|
3150 | ctr = info2->data->keys[i].values;
|
---|
3151 |
|
---|
3152 | map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
|
---|
3153 | map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
|
---|
3154 |
|
---|
3155 | /* we make the assumption that the netbios name is the same
|
---|
3156 | as the DNS name sinc ethe former will be what we used to
|
---|
3157 | join the domain */
|
---|
3158 |
|
---|
3159 | dnssuffix = get_mydnsdomname(talloc_tos());
|
---|
3160 | if (dnssuffix && *dnssuffix) {
|
---|
3161 | fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
|
---|
3162 | } else {
|
---|
3163 | fstrcpy( longname, global_myname() );
|
---|
3164 | }
|
---|
3165 |
|
---|
3166 | map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
|
---|
3167 |
|
---|
3168 | if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
|
---|
3169 | return false;
|
---|
3170 | }
|
---|
3171 | map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
|
---|
3172 | SAFE_FREE(allocated_string);
|
---|
3173 |
|
---|
3174 | map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
|
---|
3175 | map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
|
---|
3176 | map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
|
---|
3177 | map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
|
---|
3178 | map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
|
---|
3179 | map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
|
---|
3180 | map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
|
---|
3181 | map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
|
---|
3182 | map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
|
---|
3183 |
|
---|
3184 | map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
|
---|
3185 | (info2->attributes &
|
---|
3186 | PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
|
---|
3187 |
|
---|
3188 | switch (info2->attributes & 0x3) {
|
---|
3189 | case 0:
|
---|
3190 | ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
|
---|
3191 | break;
|
---|
3192 | case 1:
|
---|
3193 | ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
|
---|
3194 | break;
|
---|
3195 | case 2:
|
---|
3196 | ascii_str = SPOOL_REGVAL_PRINTDIRECT;
|
---|
3197 | break;
|
---|
3198 | default:
|
---|
3199 | ascii_str = "unknown";
|
---|
3200 | }
|
---|
3201 | map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
|
---|
3202 |
|
---|
3203 | return True;
|
---|
3204 | }
|
---|
3205 |
|
---|
3206 | /*****************************************************************
|
---|
3207 | ****************************************************************/
|
---|
3208 |
|
---|
3209 | static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
|
---|
3210 | struct GUID guid)
|
---|
3211 | {
|
---|
3212 | int i;
|
---|
3213 | REGVAL_CTR *ctr=NULL;
|
---|
3214 | UNISTR2 unistr_guid;
|
---|
3215 |
|
---|
3216 | /* find the DsSpooler key */
|
---|
3217 | if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
|
---|
3218 | i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
|
---|
3219 | ctr = info2->data->keys[i].values;
|
---|
3220 |
|
---|
3221 | regval_ctr_delvalue(ctr, "objectGUID");
|
---|
3222 |
|
---|
3223 | /* We used to store this as a REG_BINARY but that causes
|
---|
3224 | Vista to whine */
|
---|
3225 |
|
---|
3226 | ZERO_STRUCT( unistr_guid );
|
---|
3227 |
|
---|
3228 | init_unistr2( &unistr_guid, smb_uuid_string(talloc_tos(), guid),
|
---|
3229 | UNI_STR_TERMINATE );
|
---|
3230 |
|
---|
3231 | regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
|
---|
3232 | (char *)unistr_guid.buffer,
|
---|
3233 | unistr_guid.uni_max_len*2);
|
---|
3234 |
|
---|
3235 | }
|
---|
3236 |
|
---|
3237 | static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
|
---|
3238 | NT_PRINTER_INFO_LEVEL *printer)
|
---|
3239 | {
|
---|
3240 | ADS_STATUS ads_rc;
|
---|
3241 | LDAPMessage *res;
|
---|
3242 | char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
|
---|
3243 | char *srv_dn_utf8, **srv_cn_utf8;
|
---|
3244 | TALLOC_CTX *ctx;
|
---|
3245 | ADS_MODLIST mods;
|
---|
3246 | const char *attrs[] = {"objectGUID", NULL};
|
---|
3247 | struct GUID guid;
|
---|
3248 | WERROR win_rc = WERR_OK;
|
---|
3249 | size_t converted_size;
|
---|
3250 | int ret;
|
---|
3251 |
|
---|
3252 | DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
|
---|
3253 |
|
---|
3254 | /* figure out where to publish */
|
---|
3255 | ads_find_machine_acct(ads, &res, global_myname());
|
---|
3256 |
|
---|
3257 | /* We use ldap_get_dn here as we need the answer
|
---|
3258 | * in utf8 to call ldap_explode_dn(). JRA. */
|
---|
3259 |
|
---|
3260 | srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
|
---|
3261 | if (!srv_dn_utf8) {
|
---|
3262 | return WERR_SERVER_UNAVAILABLE;
|
---|
3263 | }
|
---|
3264 | ads_msgfree(ads, res);
|
---|
3265 | srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
|
---|
3266 | if (!srv_cn_utf8) {
|
---|
3267 | ldap_memfree(srv_dn_utf8);
|
---|
3268 | return WERR_SERVER_UNAVAILABLE;
|
---|
3269 | }
|
---|
3270 | /* Now convert to CH_UNIX. */
|
---|
3271 | if (!pull_utf8_allocate(&srv_dn, srv_dn_utf8, &converted_size)) {
|
---|
3272 | ldap_memfree(srv_dn_utf8);
|
---|
3273 | ldap_memfree(srv_cn_utf8);
|
---|
3274 | return WERR_SERVER_UNAVAILABLE;
|
---|
3275 | }
|
---|
3276 | if (!pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0], &converted_size)) {
|
---|
3277 | ldap_memfree(srv_dn_utf8);
|
---|
3278 | ldap_memfree(srv_cn_utf8);
|
---|
3279 | SAFE_FREE(srv_dn);
|
---|
3280 | return WERR_SERVER_UNAVAILABLE;
|
---|
3281 | }
|
---|
3282 |
|
---|
3283 | ldap_memfree(srv_dn_utf8);
|
---|
3284 | ldap_memfree(srv_cn_utf8);
|
---|
3285 |
|
---|
3286 | srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
|
---|
3287 | if (!srv_cn_escaped) {
|
---|
3288 | SAFE_FREE(srv_cn_0);
|
---|
3289 | SAFE_FREE(srv_dn);
|
---|
3290 | return WERR_SERVER_UNAVAILABLE;
|
---|
3291 | }
|
---|
3292 | sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
|
---|
3293 | if (!sharename_escaped) {
|
---|
3294 | SAFE_FREE(srv_cn_escaped);
|
---|
3295 | SAFE_FREE(srv_cn_0);
|
---|
3296 | SAFE_FREE(srv_dn);
|
---|
3297 | return WERR_SERVER_UNAVAILABLE;
|
---|
3298 | }
|
---|
3299 |
|
---|
3300 | ret = asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
|
---|
3301 |
|
---|
3302 | SAFE_FREE(srv_dn);
|
---|
3303 | SAFE_FREE(srv_cn_0);
|
---|
3304 | SAFE_FREE(srv_cn_escaped);
|
---|
3305 | SAFE_FREE(sharename_escaped);
|
---|
3306 |
|
---|
3307 | if (ret == -1) {
|
---|
3308 | return WERR_NOMEM;
|
---|
3309 | }
|
---|
3310 |
|
---|
3311 | /* build the ads mods */
|
---|
3312 | ctx = talloc_init("nt_printer_publish_ads");
|
---|
3313 | if (ctx == NULL) {
|
---|
3314 | SAFE_FREE(prt_dn);
|
---|
3315 | return WERR_NOMEM;
|
---|
3316 | }
|
---|
3317 |
|
---|
3318 | mods = ads_init_mods(ctx);
|
---|
3319 |
|
---|
3320 | if (mods == NULL) {
|
---|
3321 | SAFE_FREE(prt_dn);
|
---|
3322 | talloc_destroy(ctx);
|
---|
3323 | return WERR_NOMEM;
|
---|
3324 | }
|
---|
3325 |
|
---|
3326 | get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
|
---|
3327 | ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
|
---|
3328 | printer->info_2->sharename);
|
---|
3329 |
|
---|
3330 | /* publish it */
|
---|
3331 | ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
|
---|
3332 | if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
|
---|
3333 | int i;
|
---|
3334 | for (i=0; mods[i] != 0; i++)
|
---|
3335 | ;
|
---|
3336 | mods[i] = (LDAPMod *)-1;
|
---|
3337 | ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
|
---|
3338 | }
|
---|
3339 |
|
---|
3340 | if (!ADS_ERR_OK(ads_rc))
|
---|
3341 | DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
|
---|
3342 |
|
---|
3343 | talloc_destroy(ctx);
|
---|
3344 |
|
---|
3345 | /* retreive the guid and store it locally */
|
---|
3346 | if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
|
---|
3347 | ZERO_STRUCT(guid);
|
---|
3348 | ads_pull_guid(ads, res, &guid);
|
---|
3349 | ads_msgfree(ads, res);
|
---|
3350 | store_printer_guid(printer->info_2, guid);
|
---|
3351 | win_rc = mod_a_printer(printer, 2);
|
---|
3352 | }
|
---|
3353 |
|
---|
3354 | SAFE_FREE(prt_dn);
|
---|
3355 | return win_rc;
|
---|
3356 | }
|
---|
3357 |
|
---|
3358 | static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
|
---|
3359 | NT_PRINTER_INFO_LEVEL *printer)
|
---|
3360 | {
|
---|
3361 | ADS_STATUS ads_rc;
|
---|
3362 | LDAPMessage *res;
|
---|
3363 | char *prt_dn = NULL;
|
---|
3364 |
|
---|
3365 | DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
|
---|
3366 |
|
---|
3367 | /* remove the printer from the directory */
|
---|
3368 | ads_rc = ads_find_printer_on_server(ads, &res,
|
---|
3369 | printer->info_2->sharename, global_myname());
|
---|
3370 |
|
---|
3371 | if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
|
---|
3372 | prt_dn = ads_get_dn(ads, res);
|
---|
3373 | if (!prt_dn) {
|
---|
3374 | ads_msgfree(ads, res);
|
---|
3375 | return WERR_NOMEM;
|
---|
3376 | }
|
---|
3377 | ads_rc = ads_del_dn(ads, prt_dn);
|
---|
3378 | ads_memfree(ads, prt_dn);
|
---|
3379 | }
|
---|
3380 |
|
---|
3381 | ads_msgfree(ads, res);
|
---|
3382 | return WERR_OK;
|
---|
3383 | }
|
---|
3384 |
|
---|
3385 | /****************************************************************************
|
---|
3386 | * Publish a printer in the directory
|
---|
3387 | *
|
---|
3388 | * @param snum describing printer service
|
---|
3389 | * @return WERROR indicating status of publishing
|
---|
3390 | ***************************************************************************/
|
---|
3391 |
|
---|
3392 | WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
|
---|
3393 | {
|
---|
3394 | ADS_STATUS ads_rc;
|
---|
3395 | ADS_STRUCT *ads = NULL;
|
---|
3396 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
---|
3397 | WERROR win_rc;
|
---|
3398 |
|
---|
3399 | win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
|
---|
3400 | if (!W_ERROR_IS_OK(win_rc))
|
---|
3401 | goto done;
|
---|
3402 |
|
---|
3403 | switch (action) {
|
---|
3404 | case SPOOL_DS_PUBLISH:
|
---|
3405 | case SPOOL_DS_UPDATE:
|
---|
3406 | /* set the DsSpooler info and attributes */
|
---|
3407 | if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
|
---|
3408 | win_rc = WERR_NOMEM;
|
---|
3409 | goto done;
|
---|
3410 | }
|
---|
3411 |
|
---|
3412 | printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
|
---|
3413 | break;
|
---|
3414 | case SPOOL_DS_UNPUBLISH:
|
---|
3415 | printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
|
---|
3416 | break;
|
---|
3417 | default:
|
---|
3418 | win_rc = WERR_NOT_SUPPORTED;
|
---|
3419 | goto done;
|
---|
3420 | }
|
---|
3421 |
|
---|
3422 | win_rc = mod_a_printer(printer, 2);
|
---|
3423 | if (!W_ERROR_IS_OK(win_rc)) {
|
---|
3424 | DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
|
---|
3425 | goto done;
|
---|
3426 | }
|
---|
3427 |
|
---|
3428 | ads = ads_init(lp_realm(), lp_workgroup(), NULL);
|
---|
3429 | if (!ads) {
|
---|
3430 | DEBUG(3, ("ads_init() failed\n"));
|
---|
3431 | win_rc = WERR_SERVER_UNAVAILABLE;
|
---|
3432 | goto done;
|
---|
3433 | }
|
---|
3434 | setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
|
---|
3435 | SAFE_FREE(ads->auth.password);
|
---|
3436 | ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
|
---|
3437 | NULL, NULL);
|
---|
3438 |
|
---|
3439 | /* ads_connect() will find the DC for us */
|
---|
3440 | ads_rc = ads_connect(ads);
|
---|
3441 | if (!ADS_ERR_OK(ads_rc)) {
|
---|
3442 | DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
|
---|
3443 | win_rc = WERR_ACCESS_DENIED;
|
---|
3444 | goto done;
|
---|
3445 | }
|
---|
3446 |
|
---|
3447 | switch (action) {
|
---|
3448 | case SPOOL_DS_PUBLISH:
|
---|
3449 | case SPOOL_DS_UPDATE:
|
---|
3450 | win_rc = nt_printer_publish_ads(ads, printer);
|
---|
3451 | break;
|
---|
3452 | case SPOOL_DS_UNPUBLISH:
|
---|
3453 | win_rc = nt_printer_unpublish_ads(ads, printer);
|
---|
3454 | break;
|
---|
3455 | }
|
---|
3456 |
|
---|
3457 | done:
|
---|
3458 | free_a_printer(&printer, 2);
|
---|
3459 | ads_destroy(&ads);
|
---|
3460 | return win_rc;
|
---|
3461 | }
|
---|
3462 |
|
---|
3463 | WERROR check_published_printers(void)
|
---|
3464 | {
|
---|
3465 | ADS_STATUS ads_rc;
|
---|
3466 | ADS_STRUCT *ads = NULL;
|
---|
3467 | int snum;
|
---|
3468 | int n_services = lp_numservices();
|
---|
3469 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
---|
3470 |
|
---|
3471 | ads = ads_init(lp_realm(), lp_workgroup(), NULL);
|
---|
3472 | if (!ads) {
|
---|
3473 | DEBUG(3, ("ads_init() failed\n"));
|
---|
3474 | return WERR_SERVER_UNAVAILABLE;
|
---|
3475 | }
|
---|
3476 | setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
|
---|
3477 | SAFE_FREE(ads->auth.password);
|
---|
3478 | ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
|
---|
3479 | NULL, NULL);
|
---|
3480 |
|
---|
3481 | /* ads_connect() will find the DC for us */
|
---|
3482 | ads_rc = ads_connect(ads);
|
---|
3483 | if (!ADS_ERR_OK(ads_rc)) {
|
---|
3484 | DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
|
---|
3485 | ads_destroy(&ads);
|
---|
3486 | ads_kdestroy("MEMORY:prtpub_cache");
|
---|
3487 | return WERR_ACCESS_DENIED;
|
---|
3488 | }
|
---|
3489 |
|
---|
3490 | for (snum = 0; snum < n_services; snum++) {
|
---|
3491 | if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
|
---|
3492 | continue;
|
---|
3493 |
|
---|
3494 | if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
|
---|
3495 | lp_servicename(snum))) &&
|
---|
3496 | (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
|
---|
3497 | nt_printer_publish_ads(ads, printer);
|
---|
3498 |
|
---|
3499 | free_a_printer(&printer, 2);
|
---|
3500 | }
|
---|
3501 |
|
---|
3502 | ads_destroy(&ads);
|
---|
3503 | ads_kdestroy("MEMORY:prtpub_cache");
|
---|
3504 | return WERR_OK;
|
---|
3505 | }
|
---|
3506 |
|
---|
3507 | bool is_printer_published(Printer_entry *print_hnd, int snum,
|
---|
3508 | struct GUID *guid)
|
---|
3509 | {
|
---|
3510 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
---|
3511 | REGVAL_CTR *ctr;
|
---|
3512 | REGISTRY_VALUE *guid_val;
|
---|
3513 | WERROR win_rc;
|
---|
3514 | int i;
|
---|
3515 | bool ret = False;
|
---|
3516 |
|
---|
3517 | win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
|
---|
3518 |
|
---|
3519 | if (!W_ERROR_IS_OK(win_rc) ||
|
---|
3520 | !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
|
---|
3521 | ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
|
---|
3522 | !(ctr = printer->info_2->data->keys[i].values) ||
|
---|
3523 | !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
|
---|
3524 | {
|
---|
3525 | free_a_printer(&printer, 2);
|
---|
3526 | return False;
|
---|
3527 | }
|
---|
3528 |
|
---|
3529 | /* fetching printer guids really ought to be a separate function. */
|
---|
3530 |
|
---|
3531 | if ( guid ) {
|
---|
3532 | fstring guid_str;
|
---|
3533 |
|
---|
3534 | /* We used to store the guid as REG_BINARY, then swapped
|
---|
3535 | to REG_SZ for Vista compatibility so check for both */
|
---|
3536 |
|
---|
3537 | switch ( regval_type(guid_val) ){
|
---|
3538 | case REG_SZ:
|
---|
3539 | rpcstr_pull( guid_str, regval_data_p(guid_val),
|
---|
3540 | sizeof(guid_str)-1, -1, STR_TERMINATE );
|
---|
3541 | ret = smb_string_to_uuid( guid_str, guid );
|
---|
3542 | break;
|
---|
3543 | case REG_BINARY:
|
---|
3544 | if ( regval_size(guid_val) != sizeof(struct GUID) ) {
|
---|
3545 | ret = False;
|
---|
3546 | break;
|
---|
3547 | }
|
---|
3548 | memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
|
---|
3549 | break;
|
---|
3550 | default:
|
---|
3551 | DEBUG(0,("is_printer_published: GUID value stored as "
|
---|
3552 | "invaluid type (%d)\n", regval_type(guid_val) ));
|
---|
3553 | break;
|
---|
3554 | }
|
---|
3555 | }
|
---|
3556 |
|
---|
3557 | free_a_printer(&printer, 2);
|
---|
3558 | return ret;
|
---|
3559 | }
|
---|
3560 | #else
|
---|
3561 | WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
|
---|
3562 | {
|
---|
3563 | return WERR_OK;
|
---|
3564 | }
|
---|
3565 |
|
---|
3566 | WERROR check_published_printers(void)
|
---|
3567 | {
|
---|
3568 | return WERR_OK;
|
---|
3569 | }
|
---|
3570 |
|
---|
3571 | bool is_printer_published(Printer_entry *print_hnd, int snum,
|
---|
3572 | struct GUID *guid)
|
---|
3573 | {
|
---|
3574 | return False;
|
---|
3575 | }
|
---|
3576 | #endif /* HAVE_ADS */
|
---|
3577 |
|
---|
3578 | /****************************************************************************
|
---|
3579 | ***************************************************************************/
|
---|
3580 |
|
---|
3581 | WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
|
---|
3582 | {
|
---|
3583 | NT_PRINTER_DATA *data;
|
---|
3584 | int i;
|
---|
3585 | int removed_keys = 0;
|
---|
3586 | int empty_slot;
|
---|
3587 |
|
---|
3588 | data = p2->data;
|
---|
3589 | empty_slot = data->num_keys;
|
---|
3590 |
|
---|
3591 | if ( !key )
|
---|
3592 | return WERR_INVALID_PARAM;
|
---|
3593 |
|
---|
3594 | /* remove all keys */
|
---|
3595 |
|
---|
3596 | if ( !strlen(key) ) {
|
---|
3597 |
|
---|
3598 | TALLOC_FREE( data );
|
---|
3599 |
|
---|
3600 | p2->data = NULL;
|
---|
3601 |
|
---|
3602 | DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
|
---|
3603 | p2->printername ));
|
---|
3604 |
|
---|
3605 | return WERR_OK;
|
---|
3606 | }
|
---|
3607 |
|
---|
3608 | /* remove a specific key (and all subkeys) */
|
---|
3609 |
|
---|
3610 | for ( i=0; i<data->num_keys; i++ ) {
|
---|
3611 | if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
|
---|
3612 | DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
|
---|
3613 | data->keys[i].name));
|
---|
3614 |
|
---|
3615 | TALLOC_FREE( data->keys[i].name );
|
---|
3616 | TALLOC_FREE( data->keys[i].values );
|
---|
3617 |
|
---|
3618 | /* mark the slot as empty */
|
---|
3619 |
|
---|
3620 | ZERO_STRUCTP( &data->keys[i] );
|
---|
3621 | }
|
---|
3622 | }
|
---|
3623 |
|
---|
3624 | /* find the first empty slot */
|
---|
3625 |
|
---|
3626 | for ( i=0; i<data->num_keys; i++ ) {
|
---|
3627 | if ( !data->keys[i].name ) {
|
---|
3628 | empty_slot = i;
|
---|
3629 | removed_keys++;
|
---|
3630 | break;
|
---|
3631 | }
|
---|
3632 | }
|
---|
3633 |
|
---|
3634 | if ( i == data->num_keys )
|
---|
3635 | /* nothing was removed */
|
---|
3636 | return WERR_INVALID_PARAM;
|
---|
3637 |
|
---|
3638 | /* move everything down */
|
---|
3639 |
|
---|
3640 | for ( i=empty_slot+1; i<data->num_keys; i++ ) {
|
---|
3641 | if ( data->keys[i].name ) {
|
---|
3642 | memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
|
---|
3643 | ZERO_STRUCTP( &data->keys[i] );
|
---|
3644 | empty_slot++;
|
---|
3645 | removed_keys++;
|
---|
3646 | }
|
---|
3647 | }
|
---|
3648 |
|
---|
3649 | /* update count */
|
---|
3650 |
|
---|
3651 | data->num_keys -= removed_keys;
|
---|
3652 |
|
---|
3653 | /* sanity check to see if anything is left */
|
---|
3654 |
|
---|
3655 | if ( !data->num_keys ) {
|
---|
3656 | DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
|
---|
3657 |
|
---|
3658 | SAFE_FREE( data->keys );
|
---|
3659 | ZERO_STRUCTP( data );
|
---|
3660 | }
|
---|
3661 |
|
---|
3662 | return WERR_OK;
|
---|
3663 | }
|
---|
3664 |
|
---|
3665 | /****************************************************************************
|
---|
3666 | ***************************************************************************/
|
---|
3667 |
|
---|
3668 | WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
|
---|
3669 | {
|
---|
3670 | WERROR result = WERR_OK;
|
---|
3671 | int key_index;
|
---|
3672 |
|
---|
3673 | /* we must have names on non-zero length */
|
---|
3674 |
|
---|
3675 | if ( !key || !*key|| !value || !*value )
|
---|
3676 | return WERR_INVALID_NAME;
|
---|
3677 |
|
---|
3678 | /* find the printer key first */
|
---|
3679 |
|
---|
3680 | key_index = lookup_printerkey( p2->data, key );
|
---|
3681 | if ( key_index == -1 )
|
---|
3682 | return WERR_OK;
|
---|
3683 |
|
---|
3684 | /* make sure the value exists so we can return the correct error code */
|
---|
3685 |
|
---|
3686 | if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
|
---|
3687 | return WERR_BADFILE;
|
---|
3688 |
|
---|
3689 | regval_ctr_delvalue( p2->data->keys[key_index].values, value );
|
---|
3690 |
|
---|
3691 | DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
|
---|
3692 | key, value ));
|
---|
3693 |
|
---|
3694 | return result;
|
---|
3695 | }
|
---|
3696 |
|
---|
3697 | /****************************************************************************
|
---|
3698 | ***************************************************************************/
|
---|
3699 |
|
---|
3700 | WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
|
---|
3701 | uint32 type, uint8 *data, int real_len )
|
---|
3702 | {
|
---|
3703 | WERROR result = WERR_OK;
|
---|
3704 | int key_index;
|
---|
3705 |
|
---|
3706 | /* we must have names on non-zero length */
|
---|
3707 |
|
---|
3708 | if ( !key || !*key|| !value || !*value )
|
---|
3709 | return WERR_INVALID_NAME;
|
---|
3710 |
|
---|
3711 | /* find the printer key first */
|
---|
3712 |
|
---|
3713 | key_index = lookup_printerkey( p2->data, key );
|
---|
3714 | if ( key_index == -1 )
|
---|
3715 | key_index = add_new_printer_key( p2->data, key );
|
---|
3716 |
|
---|
3717 | if ( key_index == -1 )
|
---|
3718 | return WERR_NOMEM;
|
---|
3719 |
|
---|
3720 | regval_ctr_addvalue( p2->data->keys[key_index].values, value,
|
---|
3721 | type, (const char *)data, real_len );
|
---|
3722 |
|
---|
3723 | DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
|
---|
3724 | key, value, type, real_len ));
|
---|
3725 |
|
---|
3726 | return result;
|
---|
3727 | }
|
---|
3728 |
|
---|
3729 | /****************************************************************************
|
---|
3730 | ***************************************************************************/
|
---|
3731 |
|
---|
3732 | REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
|
---|
3733 | {
|
---|
3734 | int key_index;
|
---|
3735 |
|
---|
3736 | if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
|
---|
3737 | return NULL;
|
---|
3738 |
|
---|
3739 | DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
|
---|
3740 | key, value ));
|
---|
3741 |
|
---|
3742 | return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
|
---|
3743 | }
|
---|
3744 |
|
---|
3745 | /****************************************************************************
|
---|
3746 | Unpack a list of registry values frem the TDB
|
---|
3747 | ***************************************************************************/
|
---|
3748 |
|
---|
3749 | static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
|
---|
3750 | {
|
---|
3751 | int len = 0;
|
---|
3752 | uint32 type;
|
---|
3753 | fstring string;
|
---|
3754 | const char *valuename = NULL;
|
---|
3755 | const char *keyname = NULL;
|
---|
3756 | char *str;
|
---|
3757 | int size;
|
---|
3758 | uint8 *data_p;
|
---|
3759 | REGISTRY_VALUE *regval_p;
|
---|
3760 | int key_index;
|
---|
3761 |
|
---|
3762 | /* add the "PrinterDriverData" key first for performance reasons */
|
---|
3763 |
|
---|
3764 | add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
|
---|
3765 |
|
---|
3766 | /* loop and unpack the rest of the registry values */
|
---|
3767 |
|
---|
3768 | while ( True ) {
|
---|
3769 |
|
---|
3770 | /* check to see if there are any more registry values */
|
---|
3771 |
|
---|
3772 | regval_p = NULL;
|
---|
3773 | len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
|
---|
3774 | if ( !regval_p )
|
---|
3775 | break;
|
---|
3776 |
|
---|
3777 | /* unpack the next regval */
|
---|
3778 |
|
---|
3779 | len += tdb_unpack(buf+len, buflen-len, "fdB",
|
---|
3780 | string,
|
---|
3781 | &type,
|
---|
3782 | &size,
|
---|
3783 | &data_p);
|
---|
3784 |
|
---|
3785 | /* lookup for subkey names which have a type of REG_NONE */
|
---|
3786 | /* there's no data with this entry */
|
---|
3787 |
|
---|
3788 | if ( type == REG_NONE ) {
|
---|
3789 | if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
|
---|
3790 | add_new_printer_key( printer_data, string );
|
---|
3791 | continue;
|
---|
3792 | }
|
---|
3793 |
|
---|
3794 | /*
|
---|
3795 | * break of the keyname from the value name.
|
---|
3796 | * Valuenames can have embedded '\'s so be careful.
|
---|
3797 | * only support one level of keys. See the
|
---|
3798 | * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
|
---|
3799 | * -- jerry
|
---|
3800 | */
|
---|
3801 |
|
---|
3802 | str = strchr_m( string, '\\');
|
---|
3803 |
|
---|
3804 | /* Put in "PrinterDriverData" is no key specified */
|
---|
3805 |
|
---|
3806 | if ( !str ) {
|
---|
3807 | keyname = SPOOL_PRINTERDATA_KEY;
|
---|
3808 | valuename = string;
|
---|
3809 | }
|
---|
3810 | else {
|
---|
3811 | *str = '\0';
|
---|
3812 | keyname = string;
|
---|
3813 | valuename = str+1;
|
---|
3814 | }
|
---|
3815 |
|
---|
3816 | /* see if we need a new key */
|
---|
3817 |
|
---|
3818 | if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
|
---|
3819 | key_index = add_new_printer_key( printer_data, keyname );
|
---|
3820 |
|
---|
3821 | if ( key_index == -1 ) {
|
---|
3822 | DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
|
---|
3823 | keyname));
|
---|
3824 | break;
|
---|
3825 | }
|
---|
3826 |
|
---|
3827 | DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
|
---|
3828 |
|
---|
3829 | /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
|
---|
3830 | Thanks to Martin Zielinski for the hint. */
|
---|
3831 |
|
---|
3832 | if ( type == REG_BINARY &&
|
---|
3833 | strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
|
---|
3834 | strequal( valuename, "objectGUID" ) )
|
---|
3835 | {
|
---|
3836 | struct GUID guid;
|
---|
3837 | UNISTR2 unistr_guid;
|
---|
3838 |
|
---|
3839 | ZERO_STRUCT( unistr_guid );
|
---|
3840 |
|
---|
3841 | /* convert the GUID to a UNICODE string */
|
---|
3842 |
|
---|
3843 | memcpy( &guid, data_p, sizeof(struct GUID) );
|
---|
3844 |
|
---|
3845 | init_unistr2( &unistr_guid,
|
---|
3846 | smb_uuid_string(talloc_tos(), guid),
|
---|
3847 | UNI_STR_TERMINATE );
|
---|
3848 |
|
---|
3849 | regval_ctr_addvalue( printer_data->keys[key_index].values,
|
---|
3850 | valuename, REG_SZ,
|
---|
3851 | (const char *)unistr_guid.buffer,
|
---|
3852 | unistr_guid.uni_str_len*2 );
|
---|
3853 |
|
---|
3854 | } else {
|
---|
3855 | /* add the value */
|
---|
3856 |
|
---|
3857 | regval_ctr_addvalue( printer_data->keys[key_index].values,
|
---|
3858 | valuename, type, (const char *)data_p,
|
---|
3859 | size );
|
---|
3860 | }
|
---|
3861 |
|
---|
3862 | SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
|
---|
3863 |
|
---|
3864 | }
|
---|
3865 |
|
---|
3866 | return len;
|
---|
3867 | }
|
---|
3868 |
|
---|
3869 | /****************************************************************************
|
---|
3870 | ***************************************************************************/
|
---|
3871 |
|
---|
3872 | static char *last_from;
|
---|
3873 | static char *last_to;
|
---|
3874 |
|
---|
3875 | static const char *get_last_from(void)
|
---|
3876 | {
|
---|
3877 | if (!last_from) {
|
---|
3878 | return "";
|
---|
3879 | }
|
---|
3880 | return last_from;
|
---|
3881 | }
|
---|
3882 |
|
---|
3883 | static const char *get_last_to(void)
|
---|
3884 | {
|
---|
3885 | if (!last_to) {
|
---|
3886 | return "";
|
---|
3887 | }
|
---|
3888 | return last_to;
|
---|
3889 | }
|
---|
3890 |
|
---|
3891 | static bool set_last_from_to(const char *from, const char *to)
|
---|
3892 | {
|
---|
3893 | char *orig_from = last_from;
|
---|
3894 | char *orig_to = last_to;
|
---|
3895 |
|
---|
3896 | last_from = SMB_STRDUP(from);
|
---|
3897 | last_to = SMB_STRDUP(to);
|
---|
3898 |
|
---|
3899 | SAFE_FREE(orig_from);
|
---|
3900 | SAFE_FREE(orig_to);
|
---|
3901 |
|
---|
3902 | if (!last_from || !last_to) {
|
---|
3903 | SAFE_FREE(last_from);
|
---|
3904 | SAFE_FREE(last_to);
|
---|
3905 | return false;
|
---|
3906 | }
|
---|
3907 | return true;
|
---|
3908 | }
|
---|
3909 |
|
---|
3910 | static void map_to_os2_driver(fstring drivername)
|
---|
3911 | {
|
---|
3912 | char *mapfile = lp_os2_driver_map();
|
---|
3913 | char **lines = NULL;
|
---|
3914 | int numlines = 0;
|
---|
3915 | int i;
|
---|
3916 |
|
---|
3917 | if (!strlen(drivername))
|
---|
3918 | return;
|
---|
3919 |
|
---|
3920 | if (!*mapfile)
|
---|
3921 | return;
|
---|
3922 |
|
---|
3923 | if (strequal(drivername,get_last_from())) {
|
---|
3924 | DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
|
---|
3925 | drivername,get_last_to()));
|
---|
3926 | fstrcpy(drivername,get_last_to());
|
---|
3927 | return;
|
---|
3928 | }
|
---|
3929 |
|
---|
3930 | lines = file_lines_load(mapfile, &numlines,0);
|
---|
3931 | if (numlines == 0 || lines == NULL) {
|
---|
3932 | DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
|
---|
3933 | SAFE_FREE(lines);
|
---|
3934 | return;
|
---|
3935 | }
|
---|
3936 |
|
---|
3937 | DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
|
---|
3938 |
|
---|
3939 | for( i = 0; i < numlines; i++) {
|
---|
3940 | char *nt_name = lines[i];
|
---|
3941 | char *os2_name = strchr(nt_name,'=');
|
---|
3942 |
|
---|
3943 | if (!os2_name)
|
---|
3944 | continue;
|
---|
3945 |
|
---|
3946 | *os2_name++ = 0;
|
---|
3947 |
|
---|
3948 | while (isspace(*nt_name))
|
---|
3949 | nt_name++;
|
---|
3950 |
|
---|
3951 | if (!*nt_name || strchr("#;",*nt_name))
|
---|
3952 | continue;
|
---|
3953 |
|
---|
3954 | {
|
---|
3955 | int l = strlen(nt_name);
|
---|
3956 | while (l && isspace(nt_name[l-1])) {
|
---|
3957 | nt_name[l-1] = 0;
|
---|
3958 | l--;
|
---|
3959 | }
|
---|
3960 | }
|
---|
3961 |
|
---|
3962 | while (isspace(*os2_name))
|
---|
3963 | os2_name++;
|
---|
3964 |
|
---|
3965 | {
|
---|
3966 | int l = strlen(os2_name);
|
---|
3967 | while (l && isspace(os2_name[l-1])) {
|
---|
3968 | os2_name[l-1] = 0;
|
---|
3969 | l--;
|
---|
3970 | }
|
---|
3971 | }
|
---|
3972 |
|
---|
3973 | if (strequal(nt_name,drivername)) {
|
---|
3974 | DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
|
---|
3975 | set_last_from_to(drivername,os2_name);
|
---|
3976 | fstrcpy(drivername,os2_name);
|
---|
3977 | file_lines_free(lines);
|
---|
3978 | return;
|
---|
3979 | }
|
---|
3980 | }
|
---|
3981 |
|
---|
3982 | file_lines_free(lines);
|
---|
3983 | }
|
---|
3984 |
|
---|
3985 | /****************************************************************************
|
---|
3986 | Get a default printer info 2 struct.
|
---|
3987 | ****************************************************************************/
|
---|
3988 |
|
---|
3989 | static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
|
---|
3990 | const char *servername,
|
---|
3991 | const char* sharename,
|
---|
3992 | bool get_loc_com)
|
---|
3993 | {
|
---|
3994 | int snum = lp_servicenumber(sharename);
|
---|
3995 |
|
---|
3996 | slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
|
---|
3997 | slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
|
---|
3998 | servername, sharename);
|
---|
3999 | fstrcpy(info->sharename, sharename);
|
---|
4000 | fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
|
---|
4001 |
|
---|
4002 | /* by setting the driver name to an empty string, a local NT admin
|
---|
4003 | can now run the **local** APW to install a local printer driver
|
---|
4004 | for a Samba shared printer in 2.2. Without this, drivers **must** be
|
---|
4005 | installed on the Samba server for NT clients --jerry */
|
---|
4006 | #if 0 /* JERRY --do not uncomment-- */
|
---|
4007 | if (!*info->drivername)
|
---|
4008 | fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
|
---|
4009 | #endif
|
---|
4010 |
|
---|
4011 |
|
---|
4012 | DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
|
---|
4013 |
|
---|
4014 | strlcpy(info->comment, "", sizeof(info->comment));
|
---|
4015 | fstrcpy(info->printprocessor, "winprint");
|
---|
4016 | fstrcpy(info->datatype, "RAW");
|
---|
4017 |
|
---|
4018 | #ifdef HAVE_CUPS
|
---|
4019 | if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
|
---|
4020 | /* Pull the location and comment strings from cups if we don't
|
---|
4021 | already have one */
|
---|
4022 | if ( !strlen(info->location) || !strlen(info->comment) )
|
---|
4023 | cups_pull_comment_location( info );
|
---|
4024 | }
|
---|
4025 | #endif
|
---|
4026 |
|
---|
4027 | info->attributes = PRINTER_ATTRIBUTE_SAMBA;
|
---|
4028 |
|
---|
4029 | info->starttime = 0; /* Minutes since 12:00am GMT */
|
---|
4030 | info->untiltime = 0; /* Minutes since 12:00am GMT */
|
---|
4031 | info->priority = 1;
|
---|
4032 | info->default_priority = 1;
|
---|
4033 | info->setuptime = (uint32)time(NULL);
|
---|
4034 |
|
---|
4035 | /*
|
---|
4036 | * I changed this as I think it is better to have a generic
|
---|
4037 | * DEVMODE than to crash Win2k explorer.exe --jerry
|
---|
4038 | * See the HP Deskjet 990c Win2k drivers for an example.
|
---|
4039 | *
|
---|
4040 | * However the default devmode appears to cause problems
|
---|
4041 | * with the HP CLJ 8500 PCL driver. Hence the addition of
|
---|
4042 | * the "default devmode" parameter --jerry 22/01/2002
|
---|
4043 | */
|
---|
4044 |
|
---|
4045 | if (lp_default_devmode(snum)) {
|
---|
4046 | if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
|
---|
4047 | goto fail;
|
---|
4048 | }
|
---|
4049 | } else {
|
---|
4050 | info->devmode = NULL;
|
---|
4051 | }
|
---|
4052 |
|
---|
4053 | if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
|
---|
4054 | goto fail;
|
---|
4055 | }
|
---|
4056 |
|
---|
4057 | return WERR_OK;
|
---|
4058 |
|
---|
4059 | fail:
|
---|
4060 | if (info->devmode)
|
---|
4061 | free_nt_devicemode(&info->devmode);
|
---|
4062 |
|
---|
4063 | return WERR_ACCESS_DENIED;
|
---|
4064 | }
|
---|
4065 |
|
---|
4066 | /****************************************************************************
|
---|
4067 | ****************************************************************************/
|
---|
4068 |
|
---|
4069 | static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
|
---|
4070 | const char *servername,
|
---|
4071 | const char *sharename,
|
---|
4072 | bool get_loc_com)
|
---|
4073 | {
|
---|
4074 | int len = 0;
|
---|
4075 | int snum = lp_servicenumber(sharename);
|
---|
4076 | TDB_DATA kbuf, dbuf;
|
---|
4077 | fstring printername;
|
---|
4078 | char adevice[MAXDEVICENAME];
|
---|
4079 | char *comment = NULL;
|
---|
4080 |
|
---|
4081 | kbuf = make_printer_tdbkey(talloc_tos(), sharename);
|
---|
4082 |
|
---|
4083 | dbuf = tdb_fetch(tdb_printers, kbuf);
|
---|
4084 | if (!dbuf.dptr) {
|
---|
4085 | return get_a_printer_2_default(info, servername,
|
---|
4086 | sharename, get_loc_com);
|
---|
4087 | }
|
---|
4088 |
|
---|
4089 | len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
|
---|
4090 | &info->attributes,
|
---|
4091 | &info->priority,
|
---|
4092 | &info->default_priority,
|
---|
4093 | &info->starttime,
|
---|
4094 | &info->untiltime,
|
---|
4095 | &info->status,
|
---|
4096 | &info->cjobs,
|
---|
4097 | &info->averageppm,
|
---|
4098 | &info->changeid,
|
---|
4099 | &info->c_setprinter,
|
---|
4100 | &info->setuptime,
|
---|
4101 | info->servername,
|
---|
4102 | info->printername,
|
---|
4103 | info->sharename,
|
---|
4104 | info->portname,
|
---|
4105 | info->drivername,
|
---|
4106 | &comment,
|
---|
4107 | info->location,
|
---|
4108 | info->sepfile,
|
---|
4109 | info->printprocessor,
|
---|
4110 | info->datatype,
|
---|
4111 | info->parameters);
|
---|
4112 |
|
---|
4113 | if (comment) {
|
---|
4114 | strlcpy(info->comment, comment, sizeof(info->comment));
|
---|
4115 | SAFE_FREE(comment);
|
---|
4116 | }
|
---|
4117 |
|
---|
4118 | /* Samba has to have shared raw drivers. */
|
---|
4119 | info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
|
---|
4120 | info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
|
---|
4121 |
|
---|
4122 | /* Restore the stripped strings. */
|
---|
4123 | slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
|
---|
4124 |
|
---|
4125 | if ( lp_force_printername(snum) ) {
|
---|
4126 | slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
|
---|
4127 | } else {
|
---|
4128 | slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
|
---|
4129 | }
|
---|
4130 |
|
---|
4131 | fstrcpy(info->printername, printername);
|
---|
4132 |
|
---|
4133 | #ifdef HAVE_CUPS
|
---|
4134 | if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
|
---|
4135 | /* Pull the location and comment strings from cups if we don't
|
---|
4136 | already have one */
|
---|
4137 | if ( !strlen(info->location) || !strlen(info->comment) )
|
---|
4138 | cups_pull_comment_location( info );
|
---|
4139 | }
|
---|
4140 | #endif
|
---|
4141 |
|
---|
4142 | len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
|
---|
4143 |
|
---|
4144 | /*
|
---|
4145 | * Some client drivers freak out if there is a NULL devmode
|
---|
4146 | * (probably the driver is not checking before accessing
|
---|
4147 | * the devmode pointer) --jerry
|
---|
4148 | *
|
---|
4149 | * See comments in get_a_printer_2_default()
|
---|
4150 | */
|
---|
4151 |
|
---|
4152 | if (lp_default_devmode(snum) && !info->devmode) {
|
---|
4153 | DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
|
---|
4154 | printername));
|
---|
4155 | info->devmode = construct_nt_devicemode(printername);
|
---|
4156 | }
|
---|
4157 |
|
---|
4158 | slprintf( adevice, sizeof(adevice), "%s", info->printername );
|
---|
4159 | if (info->devmode) {
|
---|
4160 | fstrcpy(info->devmode->devicename, adevice);
|
---|
4161 | }
|
---|
4162 |
|
---|
4163 | if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
|
---|
4164 | DEBUG(0,("unpack_values: talloc() failed!\n"));
|
---|
4165 | SAFE_FREE(dbuf.dptr);
|
---|
4166 | return WERR_NOMEM;
|
---|
4167 | }
|
---|
4168 | len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
|
---|
4169 |
|
---|
4170 | /* This will get the current RPC talloc context, but we should be
|
---|
4171 | passing this as a parameter... fixme... JRA ! */
|
---|
4172 |
|
---|
4173 | if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
|
---|
4174 | SAFE_FREE(dbuf.dptr);
|
---|
4175 | return WERR_NOMEM;
|
---|
4176 | }
|
---|
4177 |
|
---|
4178 | /* Fix for OS/2 drivers. */
|
---|
4179 |
|
---|
4180 | if (get_remote_arch() == RA_OS2) {
|
---|
4181 | map_to_os2_driver(info->drivername);
|
---|
4182 | }
|
---|
4183 |
|
---|
4184 | SAFE_FREE(dbuf.dptr);
|
---|
4185 |
|
---|
4186 | DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
|
---|
4187 | sharename, info->printername, info->drivername));
|
---|
4188 |
|
---|
4189 | return WERR_OK;
|
---|
4190 | }
|
---|
4191 |
|
---|
4192 | /****************************************************************************
|
---|
4193 | Debugging function, dump at level 6 the struct in the logs.
|
---|
4194 | ****************************************************************************/
|
---|
4195 | static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
|
---|
4196 | {
|
---|
4197 | uint32 result;
|
---|
4198 | NT_PRINTER_INFO_LEVEL_2 *info2;
|
---|
4199 |
|
---|
4200 | DEBUG(106,("Dumping printer at level [%d]\n", level));
|
---|
4201 |
|
---|
4202 | switch (level) {
|
---|
4203 | case 2:
|
---|
4204 | {
|
---|
4205 | if (printer->info_2 == NULL)
|
---|
4206 | result=5;
|
---|
4207 | else
|
---|
4208 | {
|
---|
4209 | info2=printer->info_2;
|
---|
4210 |
|
---|
4211 | DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
|
---|
4212 | DEBUGADD(106,("priority:[%d]\n", info2->priority));
|
---|
4213 | DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
|
---|
4214 | DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
|
---|
4215 | DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
|
---|
4216 | DEBUGADD(106,("status:[%d]\n", info2->status));
|
---|
4217 | DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
|
---|
4218 | DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
|
---|
4219 | DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
|
---|
4220 | DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
|
---|
4221 | DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
|
---|
4222 |
|
---|
4223 | DEBUGADD(106,("servername:[%s]\n", info2->servername));
|
---|
4224 | DEBUGADD(106,("printername:[%s]\n", info2->printername));
|
---|
4225 | DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
|
---|
4226 | DEBUGADD(106,("portname:[%s]\n", info2->portname));
|
---|
4227 | DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
|
---|
4228 | DEBUGADD(106,("comment:[%s]\n", info2->comment));
|
---|
4229 | DEBUGADD(106,("location:[%s]\n", info2->location));
|
---|
4230 | DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
|
---|
4231 | DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
|
---|
4232 | DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
|
---|
4233 | DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
|
---|
4234 | result=0;
|
---|
4235 | }
|
---|
4236 | break;
|
---|
4237 | }
|
---|
4238 | default:
|
---|
4239 | DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
|
---|
4240 | result=1;
|
---|
4241 | break;
|
---|
4242 | }
|
---|
4243 |
|
---|
4244 | return result;
|
---|
4245 | }
|
---|
4246 |
|
---|
4247 | /****************************************************************************
|
---|
4248 | Update the changeid time.
|
---|
4249 | This is SO NASTY as some drivers need this to change, others need it
|
---|
4250 | static. This value will change every second, and I must hope that this
|
---|
4251 | is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
|
---|
4252 | UTAH ! JRA.
|
---|
4253 | ****************************************************************************/
|
---|
4254 |
|
---|
4255 | static uint32 rev_changeid(void)
|
---|
4256 | {
|
---|
4257 | struct timeval tv;
|
---|
4258 |
|
---|
4259 | get_process_uptime(&tv);
|
---|
4260 |
|
---|
4261 | #if 1 /* JERRY */
|
---|
4262 | /* Return changeid as msec since spooler restart */
|
---|
4263 | return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
---|
4264 | #else
|
---|
4265 | /*
|
---|
4266 | * This setting seems to work well but is too untested
|
---|
4267 | * to replace the above calculation. Left in for experiementation
|
---|
4268 | * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
|
---|
4269 | */
|
---|
4270 | return tv.tv_sec * 10 + tv.tv_usec / 100000;
|
---|
4271 | #endif
|
---|
4272 | }
|
---|
4273 |
|
---|
4274 |
|
---|
4275 | /*
|
---|
4276 | * The function below are the high level ones.
|
---|
4277 | * only those ones must be called from the spoolss code.
|
---|
4278 | * JFM.
|
---|
4279 | */
|
---|
4280 |
|
---|
4281 | /****************************************************************************
|
---|
4282 | Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
|
---|
4283 | ****************************************************************************/
|
---|
4284 |
|
---|
4285 | WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
|
---|
4286 | {
|
---|
4287 | WERROR result;
|
---|
4288 |
|
---|
4289 | dump_a_printer(printer, level);
|
---|
4290 |
|
---|
4291 | switch (level) {
|
---|
4292 | case 2:
|
---|
4293 | {
|
---|
4294 | /*
|
---|
4295 | * Update the changestamp. Emperical tests show that the
|
---|
4296 | * ChangeID is always updated,but c_setprinter is
|
---|
4297 | * global spooler variable (not per printer).
|
---|
4298 | */
|
---|
4299 |
|
---|
4300 | /* ChangeID **must** be increasing over the lifetime
|
---|
4301 | of client's spoolss service in order for the
|
---|
4302 | client's cache to show updates */
|
---|
4303 |
|
---|
4304 | printer->info_2->changeid = rev_changeid();
|
---|
4305 |
|
---|
4306 | /*
|
---|
4307 | * Because one day someone will ask:
|
---|
4308 | * NT->NT An admin connection to a remote
|
---|
4309 | * printer show changes imeediately in
|
---|
4310 | * the properities dialog
|
---|
4311 | *
|
---|
4312 | * A non-admin connection will only show the
|
---|
4313 | * changes after viewing the properites page
|
---|
4314 | * 2 times. Seems to be related to a
|
---|
4315 | * race condition in the client between the spooler
|
---|
4316 | * updating the local cache and the Explorer.exe GUI
|
---|
4317 | * actually displaying the properties.
|
---|
4318 | *
|
---|
4319 | * This is fixed in Win2k. admin/non-admin
|
---|
4320 | * connections both display changes immediately.
|
---|
4321 | *
|
---|
4322 | * 14/12/01 --jerry
|
---|
4323 | */
|
---|
4324 |
|
---|
4325 | result=update_a_printer_2(printer->info_2);
|
---|
4326 | break;
|
---|
4327 | }
|
---|
4328 | default:
|
---|
4329 | result=WERR_UNKNOWN_LEVEL;
|
---|
4330 | break;
|
---|
4331 | }
|
---|
4332 |
|
---|
4333 | return result;
|
---|
4334 | }
|
---|
4335 |
|
---|
4336 | /****************************************************************************
|
---|
4337 | Initialize printer devmode & data with previously saved driver init values.
|
---|
4338 | ****************************************************************************/
|
---|
4339 |
|
---|
4340 | static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
|
---|
4341 | {
|
---|
4342 | int len = 0;
|
---|
4343 | char *key = NULL;
|
---|
4344 | TDB_DATA dbuf;
|
---|
4345 | NT_PRINTER_INFO_LEVEL_2 info;
|
---|
4346 |
|
---|
4347 |
|
---|
4348 | ZERO_STRUCT(info);
|
---|
4349 |
|
---|
4350 | /*
|
---|
4351 | * Delete any printer data 'values' already set. When called for driver
|
---|
4352 | * replace, there will generally be some, but during an add printer, there
|
---|
4353 | * should not be any (if there are delete them).
|
---|
4354 | */
|
---|
4355 |
|
---|
4356 | if ( info_ptr->data )
|
---|
4357 | delete_all_printer_data( info_ptr, "" );
|
---|
4358 |
|
---|
4359 | if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
|
---|
4360 | info_ptr->drivername) < 0) {
|
---|
4361 | return false;
|
---|
4362 | }
|
---|
4363 |
|
---|
4364 | dbuf = tdb_fetch_bystring(tdb_drivers, key);
|
---|
4365 | if (!dbuf.dptr) {
|
---|
4366 | /*
|
---|
4367 | * When changing to a driver that has no init info in the tdb, remove
|
---|
4368 | * the previous drivers init info and leave the new on blank.
|
---|
4369 | */
|
---|
4370 | free_nt_devicemode(&info_ptr->devmode);
|
---|
4371 | SAFE_FREE(key);
|
---|
4372 | return false;
|
---|
4373 | }
|
---|
4374 |
|
---|
4375 | SAFE_FREE(key);
|
---|
4376 | /*
|
---|
4377 | * Get the saved DEVMODE..
|
---|
4378 | */
|
---|
4379 |
|
---|
4380 | len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
|
---|
4381 |
|
---|
4382 | /*
|
---|
4383 | * The saved DEVMODE contains the devicename from the printer used during
|
---|
4384 | * the initialization save. Change it to reflect the new printer.
|
---|
4385 | */
|
---|
4386 |
|
---|
4387 | if ( info.devmode ) {
|
---|
4388 | ZERO_STRUCT(info.devmode->devicename);
|
---|
4389 | fstrcpy(info.devmode->devicename, info_ptr->printername);
|
---|
4390 | }
|
---|
4391 |
|
---|
4392 | /*
|
---|
4393 | * NT/2k does not change out the entire DeviceMode of a printer
|
---|
4394 | * when changing the driver. Only the driverextra, private, &
|
---|
4395 | * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
|
---|
4396 | *
|
---|
4397 | * Later examination revealed that Windows NT/2k does reset the
|
---|
4398 | * the printer's device mode, bit **only** when you change a
|
---|
4399 | * property of the device mode such as the page orientation.
|
---|
4400 | * --jerry
|
---|
4401 | */
|
---|
4402 |
|
---|
4403 |
|
---|
4404 | /* Bind the saved DEVMODE to the new the printer */
|
---|
4405 |
|
---|
4406 | free_nt_devicemode(&info_ptr->devmode);
|
---|
4407 | info_ptr->devmode = info.devmode;
|
---|
4408 |
|
---|
4409 | DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
|
---|
4410 | info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
|
---|
4411 |
|
---|
4412 | /* Add the printer data 'values' to the new printer */
|
---|
4413 |
|
---|
4414 | if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
|
---|
4415 | DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
|
---|
4416 | return False;
|
---|
4417 | }
|
---|
4418 |
|
---|
4419 | len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
|
---|
4420 |
|
---|
4421 | SAFE_FREE(dbuf.dptr);
|
---|
4422 |
|
---|
4423 | return true;
|
---|
4424 | }
|
---|
4425 |
|
---|
4426 | /****************************************************************************
|
---|
4427 | Initialize printer devmode & data with previously saved driver init values.
|
---|
4428 | When a printer is created using AddPrinter, the drivername bound to the
|
---|
4429 | printer is used to lookup previously saved driver initialization info, which
|
---|
4430 | is bound to the new printer.
|
---|
4431 | ****************************************************************************/
|
---|
4432 |
|
---|
4433 | bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
|
---|
4434 | {
|
---|
4435 | bool result = False;
|
---|
4436 |
|
---|
4437 | switch (level) {
|
---|
4438 | case 2:
|
---|
4439 | result = set_driver_init_2(printer->info_2);
|
---|
4440 | break;
|
---|
4441 |
|
---|
4442 | default:
|
---|
4443 | DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
|
---|
4444 | level));
|
---|
4445 | break;
|
---|
4446 | }
|
---|
4447 |
|
---|
4448 | return result;
|
---|
4449 | }
|
---|
4450 |
|
---|
4451 | /****************************************************************************
|
---|
4452 | Delete driver init data stored for a specified driver
|
---|
4453 | ****************************************************************************/
|
---|
4454 |
|
---|
4455 | bool del_driver_init(char *drivername)
|
---|
4456 | {
|
---|
4457 | char *key;
|
---|
4458 | bool ret;
|
---|
4459 |
|
---|
4460 | if (!drivername || !*drivername) {
|
---|
4461 | DEBUG(3,("del_driver_init: No drivername specified!\n"));
|
---|
4462 | return false;
|
---|
4463 | }
|
---|
4464 |
|
---|
4465 | if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
|
---|
4466 | return false;
|
---|
4467 | }
|
---|
4468 |
|
---|
4469 | DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
|
---|
4470 | drivername));
|
---|
4471 |
|
---|
4472 | ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
|
---|
4473 | SAFE_FREE(key);
|
---|
4474 | return ret;
|
---|
4475 | }
|
---|
4476 |
|
---|
4477 | /****************************************************************************
|
---|
4478 | Pack up the DEVMODE and values for a printer into a 'driver init' entry
|
---|
4479 | in the tdb. Note: this is different from the driver entry and the printer
|
---|
4480 | entry. There should be a single driver init entry for each driver regardless
|
---|
4481 | of whether it was installed from NT or 2K. Technically, they should be
|
---|
4482 | different, but they work out to the same struct.
|
---|
4483 | ****************************************************************************/
|
---|
4484 |
|
---|
4485 | static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
|
---|
4486 | {
|
---|
4487 | char *key = NULL;
|
---|
4488 | uint8 *buf;
|
---|
4489 | int buflen, len, ret;
|
---|
4490 | int retlen;
|
---|
4491 | TDB_DATA dbuf;
|
---|
4492 |
|
---|
4493 | buf = NULL;
|
---|
4494 | buflen = 0;
|
---|
4495 |
|
---|
4496 | again:
|
---|
4497 | len = 0;
|
---|
4498 | len += pack_devicemode(info->devmode, buf+len, buflen-len);
|
---|
4499 |
|
---|
4500 | retlen = pack_values( info->data, buf+len, buflen-len );
|
---|
4501 | if (retlen == -1) {
|
---|
4502 | ret = -1;
|
---|
4503 | goto done;
|
---|
4504 | }
|
---|
4505 | len += retlen;
|
---|
4506 |
|
---|
4507 | if (buflen < len) {
|
---|
4508 | buf = (uint8 *)SMB_REALLOC(buf, len);
|
---|
4509 | if (!buf) {
|
---|
4510 | DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
|
---|
4511 | ret = -1;
|
---|
4512 | goto done;
|
---|
4513 | }
|
---|
4514 | buflen = len;
|
---|
4515 | goto again;
|
---|
4516 | }
|
---|
4517 |
|
---|
4518 | SAFE_FREE(key);
|
---|
4519 | if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
|
---|
4520 | ret = (uint32)-1;
|
---|
4521 | goto done;
|
---|
4522 | }
|
---|
4523 |
|
---|
4524 | dbuf.dptr = buf;
|
---|
4525 | dbuf.dsize = len;
|
---|
4526 |
|
---|
4527 | ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
|
---|
4528 |
|
---|
4529 | done:
|
---|
4530 | if (ret == -1)
|
---|
4531 | DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
|
---|
4532 |
|
---|
4533 | SAFE_FREE(buf);
|
---|
4534 |
|
---|
4535 | DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
|
---|
4536 | info->sharename, info->drivername));
|
---|
4537 |
|
---|
4538 | return ret;
|
---|
4539 | }
|
---|
4540 |
|
---|
4541 | /****************************************************************************
|
---|
4542 | Update (i.e. save) the driver init info (DEVMODE and values) for a printer
|
---|
4543 | ****************************************************************************/
|
---|
4544 |
|
---|
4545 | static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
|
---|
4546 | {
|
---|
4547 | uint32 result;
|
---|
4548 |
|
---|
4549 | dump_a_printer(printer, level);
|
---|
4550 |
|
---|
4551 | switch (level) {
|
---|
4552 | case 2:
|
---|
4553 | result = update_driver_init_2(printer->info_2);
|
---|
4554 | break;
|
---|
4555 | default:
|
---|
4556 | result = 1;
|
---|
4557 | break;
|
---|
4558 | }
|
---|
4559 |
|
---|
4560 | return result;
|
---|
4561 | }
|
---|
4562 |
|
---|
4563 | /****************************************************************************
|
---|
4564 | Convert the printer data value, a REG_BINARY array, into an initialization
|
---|
4565 | DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
|
---|
4566 | got to keep the endians happy :).
|
---|
4567 | ****************************************************************************/
|
---|
4568 |
|
---|
4569 | static bool convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
|
---|
4570 | {
|
---|
4571 | bool result = False;
|
---|
4572 | prs_struct ps;
|
---|
4573 | DEVICEMODE devmode;
|
---|
4574 |
|
---|
4575 | ZERO_STRUCT(devmode);
|
---|
4576 |
|
---|
4577 | prs_init_empty(&ps, ctx, UNMARSHALL);
|
---|
4578 | ps.data_p = (char *)data;
|
---|
4579 | ps.buffer_size = data_len;
|
---|
4580 |
|
---|
4581 | if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
|
---|
4582 | result = convert_devicemode("", &devmode, &nt_devmode);
|
---|
4583 | else
|
---|
4584 | DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
|
---|
4585 |
|
---|
4586 | return result;
|
---|
4587 | }
|
---|
4588 |
|
---|
4589 | /****************************************************************************
|
---|
4590 | Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
|
---|
4591 |
|
---|
4592 | 1. Use the driver's config DLL to this UNC printername and:
|
---|
4593 | a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
|
---|
4594 | b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
|
---|
4595 | 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
|
---|
4596 |
|
---|
4597 | The last step triggers saving the "driver initialization" information for
|
---|
4598 | this printer into the tdb. Later, new printers that use this driver will
|
---|
4599 | have this initialization information bound to them. This simulates the
|
---|
4600 | driver initialization, as if it had run on the Samba server (as it would
|
---|
4601 | have done on NT).
|
---|
4602 |
|
---|
4603 | The Win32 client side code requirement sucks! But until we can run arbitrary
|
---|
4604 | Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
|
---|
4605 |
|
---|
4606 | It would have been easier to use SetPrinter because all the UNMARSHALLING of
|
---|
4607 | the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
|
---|
4608 | about it and you will realize why. JRR 010720
|
---|
4609 | ****************************************************************************/
|
---|
4610 |
|
---|
4611 | static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
|
---|
4612 | {
|
---|
4613 | WERROR status = WERR_OK;
|
---|
4614 | TALLOC_CTX *ctx = NULL;
|
---|
4615 | NT_DEVICEMODE *nt_devmode = NULL;
|
---|
4616 | NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
|
---|
4617 |
|
---|
4618 | /*
|
---|
4619 | * When the DEVMODE is already set on the printer, don't try to unpack it.
|
---|
4620 | */
|
---|
4621 | DEBUG(8,("save_driver_init_2: Enter...\n"));
|
---|
4622 |
|
---|
4623 | if ( !printer->info_2->devmode && data_len ) {
|
---|
4624 | /*
|
---|
4625 | * Set devmode on printer info, so entire printer initialization can be
|
---|
4626 | * saved to tdb.
|
---|
4627 | */
|
---|
4628 |
|
---|
4629 | if ((ctx = talloc_init("save_driver_init_2")) == NULL)
|
---|
4630 | return WERR_NOMEM;
|
---|
4631 |
|
---|
4632 | if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
|
---|
4633 | status = WERR_NOMEM;
|
---|
4634 | goto done;
|
---|
4635 | }
|
---|
4636 |
|
---|
4637 | ZERO_STRUCTP(nt_devmode);
|
---|
4638 |
|
---|
4639 | /*
|
---|
4640 | * The DEVMODE is held in the 'data' component of the param in raw binary.
|
---|
4641 | * Convert it to to a devmode structure
|
---|
4642 | */
|
---|
4643 | if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
|
---|
4644 | DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
|
---|
4645 | status = WERR_INVALID_PARAM;
|
---|
4646 | goto done;
|
---|
4647 | }
|
---|
4648 |
|
---|
4649 | printer->info_2->devmode = nt_devmode;
|
---|
4650 | }
|
---|
4651 |
|
---|
4652 | /*
|
---|
4653 | * Pack up and add (or update) the DEVMODE and any current printer data to
|
---|
4654 | * a 'driver init' element in the tdb
|
---|
4655 | *
|
---|
4656 | */
|
---|
4657 |
|
---|
4658 | if ( update_driver_init(printer, 2) != 0 ) {
|
---|
4659 | DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
|
---|
4660 | status = WERR_NOMEM;
|
---|
4661 | goto done;
|
---|
4662 | }
|
---|
4663 |
|
---|
4664 | /*
|
---|
4665 | * If driver initialization info was successfully saved, set the current
|
---|
4666 | * printer to match it. This allows initialization of the current printer
|
---|
4667 | * as well as the driver.
|
---|
4668 | */
|
---|
4669 | status = mod_a_printer(printer, 2);
|
---|
4670 | if (!W_ERROR_IS_OK(status)) {
|
---|
4671 | DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
|
---|
4672 | printer->info_2->printername));
|
---|
4673 | }
|
---|
4674 |
|
---|
4675 | done:
|
---|
4676 | talloc_destroy(ctx);
|
---|
4677 | free_nt_devicemode( &nt_devmode );
|
---|
4678 |
|
---|
4679 | printer->info_2->devmode = tmp_devmode;
|
---|
4680 |
|
---|
4681 | return status;
|
---|
4682 | }
|
---|
4683 |
|
---|
4684 | /****************************************************************************
|
---|
4685 | Update the driver init info (DEVMODE and specifics) for a printer
|
---|
4686 | ****************************************************************************/
|
---|
4687 |
|
---|
4688 | WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
|
---|
4689 | {
|
---|
4690 | WERROR status = WERR_OK;
|
---|
4691 |
|
---|
4692 | switch (level) {
|
---|
4693 | case 2:
|
---|
4694 | status = save_driver_init_2( printer, data, data_len );
|
---|
4695 | break;
|
---|
4696 | default:
|
---|
4697 | status = WERR_UNKNOWN_LEVEL;
|
---|
4698 | break;
|
---|
4699 | }
|
---|
4700 |
|
---|
4701 | return status;
|
---|
4702 | }
|
---|
4703 |
|
---|
4704 | /****************************************************************************
|
---|
4705 | Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
|
---|
4706 |
|
---|
4707 | Previously the code had a memory allocation problem because it always
|
---|
4708 | used the TALLOC_CTX from the Printer_entry*. This context lasts
|
---|
4709 | as a long as the original handle is open. So if the client made a lot
|
---|
4710 | of getprinter[data]() calls, the memory usage would climb. Now we use
|
---|
4711 | a short lived TALLOC_CTX for printer_info_2 objects returned. We
|
---|
4712 | still use the Printer_entry->ctx for maintaining the cache copy though
|
---|
4713 | since that object must live as long as the handle by definition.
|
---|
4714 | --jerry
|
---|
4715 |
|
---|
4716 | ****************************************************************************/
|
---|
4717 |
|
---|
4718 | static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
|
---|
4719 | const char *sharename, bool get_loc_com)
|
---|
4720 | {
|
---|
4721 | WERROR result;
|
---|
4722 | fstring servername;
|
---|
4723 |
|
---|
4724 | DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
|
---|
4725 |
|
---|
4726 | if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
|
---|
4727 | DEBUG(0,("get_a_printer: talloc() fail.\n"));
|
---|
4728 | return WERR_NOMEM;
|
---|
4729 | }
|
---|
4730 |
|
---|
4731 | switch (level) {
|
---|
4732 | case 2:
|
---|
4733 | if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
|
---|
4734 | DEBUG(0,("get_a_printer: talloc() fail.\n"));
|
---|
4735 | TALLOC_FREE( *pp_printer );
|
---|
4736 | return WERR_NOMEM;
|
---|
4737 | }
|
---|
4738 |
|
---|
4739 | if ( print_hnd )
|
---|
4740 | fstrcpy( servername, print_hnd->servername );
|
---|
4741 | else {
|
---|
4742 | fstrcpy( servername, "%L" );
|
---|
4743 | standard_sub_basic( "", "", servername,
|
---|
4744 | sizeof(servername)-1 );
|
---|
4745 | }
|
---|
4746 |
|
---|
4747 | result = get_a_printer_2( (*pp_printer)->info_2,
|
---|
4748 | servername, sharename, get_loc_com);
|
---|
4749 |
|
---|
4750 | /* we have a new printer now. Save it with this handle */
|
---|
4751 |
|
---|
4752 | if ( !W_ERROR_IS_OK(result) ) {
|
---|
4753 | TALLOC_FREE( *pp_printer );
|
---|
4754 | DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
|
---|
4755 | sharename, (unsigned int)level, dos_errstr(result)));
|
---|
4756 | return result;
|
---|
4757 | }
|
---|
4758 |
|
---|
4759 | dump_a_printer( *pp_printer, level);
|
---|
4760 |
|
---|
4761 | break;
|
---|
4762 |
|
---|
4763 | default:
|
---|
4764 | TALLOC_FREE( *pp_printer );
|
---|
4765 | return WERR_UNKNOWN_LEVEL;
|
---|
4766 | }
|
---|
4767 |
|
---|
4768 | return WERR_OK;
|
---|
4769 | }
|
---|
4770 |
|
---|
4771 | WERROR get_a_printer( Printer_entry *print_hnd,
|
---|
4772 | NT_PRINTER_INFO_LEVEL **pp_printer,
|
---|
4773 | uint32 level,
|
---|
4774 | const char *sharename)
|
---|
4775 | {
|
---|
4776 | return get_a_printer_internal(print_hnd, pp_printer, level,
|
---|
4777 | sharename, true);
|
---|
4778 | }
|
---|
4779 |
|
---|
4780 | WERROR get_a_printer_search( Printer_entry *print_hnd,
|
---|
4781 | NT_PRINTER_INFO_LEVEL **pp_printer,
|
---|
4782 | uint32 level,
|
---|
4783 | const char *sharename)
|
---|
4784 | {
|
---|
4785 | return get_a_printer_internal(print_hnd, pp_printer, level,
|
---|
4786 | sharename, false);
|
---|
4787 | }
|
---|
4788 |
|
---|
4789 | /****************************************************************************
|
---|
4790 | Deletes a NT_PRINTER_INFO_LEVEL struct.
|
---|
4791 | ****************************************************************************/
|
---|
4792 |
|
---|
4793 | uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
|
---|
4794 | {
|
---|
4795 | NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
|
---|
4796 |
|
---|
4797 | if ( !printer )
|
---|
4798 | return 0;
|
---|
4799 |
|
---|
4800 | switch (level) {
|
---|
4801 | case 2:
|
---|
4802 | if ( printer->info_2 )
|
---|
4803 | free_nt_printer_info_level_2(&printer->info_2);
|
---|
4804 | break;
|
---|
4805 |
|
---|
4806 | default:
|
---|
4807 | DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
|
---|
4808 | return 1;
|
---|
4809 | }
|
---|
4810 |
|
---|
4811 | TALLOC_FREE(*pp_printer);
|
---|
4812 |
|
---|
4813 | return 0;
|
---|
4814 | }
|
---|
4815 |
|
---|
4816 | /****************************************************************************
|
---|
4817 | ****************************************************************************/
|
---|
4818 | uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
|
---|
4819 | {
|
---|
4820 | uint32 result;
|
---|
4821 | DEBUG(104,("adding a printer at level [%d]\n", level));
|
---|
4822 | dump_a_printer_driver(driver, level);
|
---|
4823 |
|
---|
4824 | switch (level) {
|
---|
4825 | case 3:
|
---|
4826 | result=add_a_printer_driver_3(driver.info_3);
|
---|
4827 | break;
|
---|
4828 |
|
---|
4829 | case 6:
|
---|
4830 | result=add_a_printer_driver_6(driver.info_6);
|
---|
4831 | break;
|
---|
4832 |
|
---|
4833 | default:
|
---|
4834 | result=1;
|
---|
4835 | break;
|
---|
4836 | }
|
---|
4837 |
|
---|
4838 | return result;
|
---|
4839 | }
|
---|
4840 | /****************************************************************************
|
---|
4841 | ****************************************************************************/
|
---|
4842 |
|
---|
4843 | WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
|
---|
4844 | fstring drivername, const char *architecture, uint32 version)
|
---|
4845 | {
|
---|
4846 | WERROR result;
|
---|
4847 |
|
---|
4848 | switch (level) {
|
---|
4849 | case 3:
|
---|
4850 | /* Sometime we just want any version of the driver */
|
---|
4851 |
|
---|
4852 | if ( version == DRIVER_ANY_VERSION ) {
|
---|
4853 | /* look for Win2k first and then for NT4 */
|
---|
4854 | result = get_a_printer_driver_3(&driver->info_3, drivername,
|
---|
4855 | architecture, 3);
|
---|
4856 |
|
---|
4857 | if ( !W_ERROR_IS_OK(result) ) {
|
---|
4858 | result = get_a_printer_driver_3( &driver->info_3,
|
---|
4859 | drivername, architecture, 2 );
|
---|
4860 | }
|
---|
4861 | } else {
|
---|
4862 | result = get_a_printer_driver_3(&driver->info_3, drivername,
|
---|
4863 | architecture, version);
|
---|
4864 | }
|
---|
4865 | break;
|
---|
4866 |
|
---|
4867 | default:
|
---|
4868 | result=W_ERROR(1);
|
---|
4869 | break;
|
---|
4870 | }
|
---|
4871 |
|
---|
4872 | if (W_ERROR_IS_OK(result))
|
---|
4873 | dump_a_printer_driver(*driver, level);
|
---|
4874 |
|
---|
4875 | return result;
|
---|
4876 | }
|
---|
4877 |
|
---|
4878 | /****************************************************************************
|
---|
4879 | ****************************************************************************/
|
---|
4880 | uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
|
---|
4881 | {
|
---|
4882 | uint32 result;
|
---|
4883 |
|
---|
4884 | switch (level) {
|
---|
4885 | case 3:
|
---|
4886 | {
|
---|
4887 | NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
|
---|
4888 | if (driver.info_3 != NULL)
|
---|
4889 | {
|
---|
4890 | info3=driver.info_3;
|
---|
4891 | SAFE_FREE(info3->dependentfiles);
|
---|
4892 | ZERO_STRUCTP(info3);
|
---|
4893 | SAFE_FREE(info3);
|
---|
4894 | result=0;
|
---|
4895 | } else {
|
---|
4896 | result=4;
|
---|
4897 | }
|
---|
4898 | break;
|
---|
4899 | }
|
---|
4900 | case 6:
|
---|
4901 | {
|
---|
4902 | NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
|
---|
4903 | if (driver.info_6 != NULL) {
|
---|
4904 | info6=driver.info_6;
|
---|
4905 | SAFE_FREE(info6->dependentfiles);
|
---|
4906 | SAFE_FREE(info6->previousnames);
|
---|
4907 | ZERO_STRUCTP(info6);
|
---|
4908 | SAFE_FREE(info6);
|
---|
4909 | result=0;
|
---|
4910 | } else {
|
---|
4911 | result=4;
|
---|
4912 | }
|
---|
4913 | break;
|
---|
4914 | }
|
---|
4915 | default:
|
---|
4916 | result=1;
|
---|
4917 | break;
|
---|
4918 | }
|
---|
4919 | return result;
|
---|
4920 | }
|
---|
4921 |
|
---|
4922 |
|
---|
4923 | /****************************************************************************
|
---|
4924 | Determine whether or not a particular driver is currently assigned
|
---|
4925 | to a printer
|
---|
4926 | ****************************************************************************/
|
---|
4927 |
|
---|
4928 | bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
|
---|
4929 | {
|
---|
4930 | int snum;
|
---|
4931 | int n_services = lp_numservices();
|
---|
4932 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
---|
4933 | bool in_use = False;
|
---|
4934 |
|
---|
4935 | if ( !info_3 )
|
---|
4936 | return False;
|
---|
4937 |
|
---|
4938 | DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
|
---|
4939 |
|
---|
4940 | /* loop through the printers.tdb and check for the drivername */
|
---|
4941 |
|
---|
4942 | for (snum=0; snum<n_services && !in_use; snum++) {
|
---|
4943 | if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
|
---|
4944 | continue;
|
---|
4945 |
|
---|
4946 | if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
|
---|
4947 | continue;
|
---|
4948 |
|
---|
4949 | if ( strequal(info_3->name, printer->info_2->drivername) )
|
---|
4950 | in_use = True;
|
---|
4951 |
|
---|
4952 | free_a_printer( &printer, 2 );
|
---|
4953 | }
|
---|
4954 |
|
---|
4955 | DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
|
---|
4956 |
|
---|
4957 | if ( in_use ) {
|
---|
4958 | NT_PRINTER_DRIVER_INFO_LEVEL d;
|
---|
4959 | WERROR werr;
|
---|
4960 |
|
---|
4961 | DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
|
---|
4962 |
|
---|
4963 | /* we can still remove the driver if there is one of
|
---|
4964 | "Windows NT x86" version 2 or 3 left */
|
---|
4965 |
|
---|
4966 | if ( !strequal( "Windows NT x86", info_3->environment ) ) {
|
---|
4967 | werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
|
---|
4968 | }
|
---|
4969 | else {
|
---|
4970 | switch ( info_3->cversion ) {
|
---|
4971 | case 2:
|
---|
4972 | werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
|
---|
4973 | break;
|
---|
4974 | case 3:
|
---|
4975 | werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
|
---|
4976 | break;
|
---|
4977 | default:
|
---|
4978 | DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
|
---|
4979 | info_3->cversion));
|
---|
4980 | werr = WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
4981 | break;
|
---|
4982 | }
|
---|
4983 | }
|
---|
4984 |
|
---|
4985 | /* now check the error code */
|
---|
4986 |
|
---|
4987 | if ( W_ERROR_IS_OK(werr) ) {
|
---|
4988 | /* it's ok to remove the driver, we have other architctures left */
|
---|
4989 | in_use = False;
|
---|
4990 | free_a_printer_driver( d, 3 );
|
---|
4991 | }
|
---|
4992 | }
|
---|
4993 |
|
---|
4994 | /* report that the driver is not in use by default */
|
---|
4995 |
|
---|
4996 | return in_use;
|
---|
4997 | }
|
---|
4998 |
|
---|
4999 |
|
---|
5000 | /**********************************************************************
|
---|
5001 | Check to see if a ogiven file is in use by *info
|
---|
5002 | *********************************************************************/
|
---|
5003 |
|
---|
5004 | static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
|
---|
5005 | {
|
---|
5006 | int i = 0;
|
---|
5007 |
|
---|
5008 | if ( !info )
|
---|
5009 | return False;
|
---|
5010 |
|
---|
5011 | /* mz: skip files that are in the list but already deleted */
|
---|
5012 | if (!file || !file[0]) {
|
---|
5013 | return false;
|
---|
5014 | }
|
---|
5015 |
|
---|
5016 | if ( strequal(file, info->driverpath) )
|
---|
5017 | return True;
|
---|
5018 |
|
---|
5019 | if ( strequal(file, info->datafile) )
|
---|
5020 | return True;
|
---|
5021 |
|
---|
5022 | if ( strequal(file, info->configfile) )
|
---|
5023 | return True;
|
---|
5024 |
|
---|
5025 | if ( strequal(file, info->helpfile) )
|
---|
5026 | return True;
|
---|
5027 |
|
---|
5028 | /* see of there are any dependent files to examine */
|
---|
5029 |
|
---|
5030 | if ( !info->dependentfiles )
|
---|
5031 | return False;
|
---|
5032 |
|
---|
5033 | while ( *info->dependentfiles[i] ) {
|
---|
5034 | if ( strequal(file, info->dependentfiles[i]) )
|
---|
5035 | return True;
|
---|
5036 | i++;
|
---|
5037 | }
|
---|
5038 |
|
---|
5039 | return False;
|
---|
5040 |
|
---|
5041 | }
|
---|
5042 |
|
---|
5043 | /**********************************************************************
|
---|
5044 | Utility function to remove the dependent file pointed to by the
|
---|
5045 | input parameter from the list
|
---|
5046 | *********************************************************************/
|
---|
5047 |
|
---|
5048 | static void trim_dependent_file( fstring files[], int idx )
|
---|
5049 | {
|
---|
5050 |
|
---|
5051 | /* bump everything down a slot */
|
---|
5052 |
|
---|
5053 | while( *files[idx+1] ) {
|
---|
5054 | fstrcpy( files[idx], files[idx+1] );
|
---|
5055 | idx++;
|
---|
5056 | }
|
---|
5057 |
|
---|
5058 | *files[idx] = '\0';
|
---|
5059 |
|
---|
5060 | return;
|
---|
5061 | }
|
---|
5062 |
|
---|
5063 | /**********************************************************************
|
---|
5064 | Check if any of the files used by src are also used by drv
|
---|
5065 | *********************************************************************/
|
---|
5066 |
|
---|
5067 | static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
|
---|
5068 | NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
|
---|
5069 | {
|
---|
5070 | bool in_use = False;
|
---|
5071 | int i = 0;
|
---|
5072 |
|
---|
5073 | if ( !src || !drv )
|
---|
5074 | return False;
|
---|
5075 |
|
---|
5076 | /* check each file. Remove it from the src structure if it overlaps */
|
---|
5077 |
|
---|
5078 | if ( drv_file_in_use(src->driverpath, drv) ) {
|
---|
5079 | in_use = True;
|
---|
5080 | DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
|
---|
5081 | fstrcpy( src->driverpath, "" );
|
---|
5082 | }
|
---|
5083 |
|
---|
5084 | if ( drv_file_in_use(src->datafile, drv) ) {
|
---|
5085 | in_use = True;
|
---|
5086 | DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
|
---|
5087 | fstrcpy( src->datafile, "" );
|
---|
5088 | }
|
---|
5089 |
|
---|
5090 | if ( drv_file_in_use(src->configfile, drv) ) {
|
---|
5091 | in_use = True;
|
---|
5092 | DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
|
---|
5093 | fstrcpy( src->configfile, "" );
|
---|
5094 | }
|
---|
5095 |
|
---|
5096 | if ( drv_file_in_use(src->helpfile, drv) ) {
|
---|
5097 | in_use = True;
|
---|
5098 | DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
|
---|
5099 | fstrcpy( src->helpfile, "" );
|
---|
5100 | }
|
---|
5101 |
|
---|
5102 | /* are there any dependentfiles to examine? */
|
---|
5103 |
|
---|
5104 | if ( !src->dependentfiles )
|
---|
5105 | return in_use;
|
---|
5106 |
|
---|
5107 | while ( *src->dependentfiles[i] ) {
|
---|
5108 | if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
|
---|
5109 | in_use = True;
|
---|
5110 | DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
|
---|
5111 | trim_dependent_file( src->dependentfiles, i );
|
---|
5112 | } else
|
---|
5113 | i++;
|
---|
5114 | }
|
---|
5115 |
|
---|
5116 | return in_use;
|
---|
5117 | }
|
---|
5118 |
|
---|
5119 | /****************************************************************************
|
---|
5120 | Determine whether or not a particular driver files are currently being
|
---|
5121 | used by any other driver.
|
---|
5122 |
|
---|
5123 | Return value is True if any files were in use by other drivers
|
---|
5124 | and False otherwise.
|
---|
5125 |
|
---|
5126 | Upon return, *info has been modified to only contain the driver files
|
---|
5127 | which are not in use
|
---|
5128 |
|
---|
5129 | Fix from mz:
|
---|
5130 |
|
---|
5131 | This needs to check all drivers to ensure that all files in use
|
---|
5132 | have been removed from *info, not just the ones in the first
|
---|
5133 | match.
|
---|
5134 | ****************************************************************************/
|
---|
5135 |
|
---|
5136 | bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
|
---|
5137 | {
|
---|
5138 | int i;
|
---|
5139 | int ndrivers;
|
---|
5140 | uint32 version;
|
---|
5141 | fstring *list = NULL;
|
---|
5142 | NT_PRINTER_DRIVER_INFO_LEVEL driver;
|
---|
5143 | bool in_use = false;
|
---|
5144 |
|
---|
5145 | if ( !info )
|
---|
5146 | return False;
|
---|
5147 |
|
---|
5148 | version = info->cversion;
|
---|
5149 |
|
---|
5150 | /* loop over all driver versions */
|
---|
5151 |
|
---|
5152 | DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
|
---|
5153 |
|
---|
5154 | /* get the list of drivers */
|
---|
5155 |
|
---|
5156 | list = NULL;
|
---|
5157 | ndrivers = get_ntdrivers(&list, info->environment, version);
|
---|
5158 |
|
---|
5159 | DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
|
---|
5160 | ndrivers, info->environment, version));
|
---|
5161 |
|
---|
5162 | /* check each driver for overlap in files */
|
---|
5163 |
|
---|
5164 | for (i=0; i<ndrivers; i++) {
|
---|
5165 | DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
|
---|
5166 |
|
---|
5167 | ZERO_STRUCT(driver);
|
---|
5168 |
|
---|
5169 | if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
|
---|
5170 | SAFE_FREE(list);
|
---|
5171 | return True;
|
---|
5172 | }
|
---|
5173 |
|
---|
5174 | /* check if d2 uses any files from d1 */
|
---|
5175 | /* only if this is a different driver than the one being deleted */
|
---|
5176 |
|
---|
5177 | if ( !strequal(info->name, driver.info_3->name) ) {
|
---|
5178 | if ( trim_overlap_drv_files(info, driver.info_3) ) {
|
---|
5179 | /* mz: Do not instantly return -
|
---|
5180 | * we need to ensure this file isn't
|
---|
5181 | * also in use by other drivers. */
|
---|
5182 | in_use = true;
|
---|
5183 | }
|
---|
5184 | }
|
---|
5185 |
|
---|
5186 | free_a_printer_driver(driver, 3);
|
---|
5187 | }
|
---|
5188 |
|
---|
5189 | SAFE_FREE(list);
|
---|
5190 |
|
---|
5191 | DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
|
---|
5192 |
|
---|
5193 | driver.info_3 = info;
|
---|
5194 |
|
---|
5195 | if ( DEBUGLEVEL >= 20 )
|
---|
5196 | dump_a_printer_driver( driver, 3 );
|
---|
5197 |
|
---|
5198 | return in_use;
|
---|
5199 | }
|
---|
5200 |
|
---|
5201 | /****************************************************************************
|
---|
5202 | Actually delete the driver files. Make sure that
|
---|
5203 | printer_driver_files_in_use() return False before calling
|
---|
5204 | this.
|
---|
5205 | ****************************************************************************/
|
---|
5206 |
|
---|
5207 | static bool delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
|
---|
5208 | {
|
---|
5209 | int i = 0;
|
---|
5210 | char *s;
|
---|
5211 | const char *file;
|
---|
5212 | connection_struct *conn;
|
---|
5213 | DATA_BLOB null_pw;
|
---|
5214 | NTSTATUS nt_status;
|
---|
5215 | fstring res_type;
|
---|
5216 | SMB_STRUCT_STAT st;
|
---|
5217 |
|
---|
5218 | if ( !info_3 )
|
---|
5219 | return False;
|
---|
5220 |
|
---|
5221 | DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
|
---|
5222 |
|
---|
5223 | /*
|
---|
5224 | * Connect to the print$ share under the same account as the
|
---|
5225 | * user connected to the rpc pipe. Note we must be root to
|
---|
5226 | * do this.
|
---|
5227 | */
|
---|
5228 |
|
---|
5229 | null_pw = data_blob_null;
|
---|
5230 | fstrcpy(res_type, "A:");
|
---|
5231 | become_root();
|
---|
5232 | conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
|
---|
5233 | unbecome_root();
|
---|
5234 |
|
---|
5235 | if ( !conn ) {
|
---|
5236 | DEBUG(0,("delete_driver_files: Unable to connect\n"));
|
---|
5237 | return False;
|
---|
5238 | }
|
---|
5239 |
|
---|
5240 | if ( !CAN_WRITE(conn) ) {
|
---|
5241 | DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
|
---|
5242 | return False;
|
---|
5243 | }
|
---|
5244 |
|
---|
5245 | /* Save who we are - we are temporarily becoming the connection user. */
|
---|
5246 |
|
---|
5247 | if ( !become_user(conn, conn->vuid) ) {
|
---|
5248 | DEBUG(0,("delete_driver_files: Can't become user!\n"));
|
---|
5249 | return False;
|
---|
5250 | }
|
---|
5251 |
|
---|
5252 | /* now delete the files; must strip the '\print$' string from
|
---|
5253 | fron of path */
|
---|
5254 |
|
---|
5255 | if ( *info_3->driverpath ) {
|
---|
5256 | if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
|
---|
5257 | file = s;
|
---|
5258 | driver_unix_convert(conn,file,&st);
|
---|
5259 | DEBUG(10,("deleting driverfile [%s]\n", s));
|
---|
5260 | unlink_internals(conn, NULL, 0, file, False);
|
---|
5261 | }
|
---|
5262 | }
|
---|
5263 |
|
---|
5264 | if ( *info_3->configfile ) {
|
---|
5265 | if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
|
---|
5266 | file = s;
|
---|
5267 | driver_unix_convert(conn,file,&st);
|
---|
5268 | DEBUG(10,("deleting configfile [%s]\n", s));
|
---|
5269 | unlink_internals(conn, NULL, 0, file, False);
|
---|
5270 | }
|
---|
5271 | }
|
---|
5272 |
|
---|
5273 | if ( *info_3->datafile ) {
|
---|
5274 | if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
|
---|
5275 | file = s;
|
---|
5276 | driver_unix_convert(conn,file,&st);
|
---|
5277 | DEBUG(10,("deleting datafile [%s]\n", s));
|
---|
5278 | unlink_internals(conn, NULL, 0, file, False);
|
---|
5279 | }
|
---|
5280 | }
|
---|
5281 |
|
---|
5282 | if ( *info_3->helpfile ) {
|
---|
5283 | if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
|
---|
5284 | file = s;
|
---|
5285 | driver_unix_convert(conn,file,&st);
|
---|
5286 | DEBUG(10,("deleting helpfile [%s]\n", s));
|
---|
5287 | unlink_internals(conn, NULL, 0, file, False);
|
---|
5288 | }
|
---|
5289 | }
|
---|
5290 |
|
---|
5291 | /* check if we are done removing files */
|
---|
5292 |
|
---|
5293 | if ( info_3->dependentfiles ) {
|
---|
5294 | while ( info_3->dependentfiles[i][0] ) {
|
---|
5295 | char *p;
|
---|
5296 |
|
---|
5297 | /* bypass the "\print$" portion of the path */
|
---|
5298 |
|
---|
5299 | if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
|
---|
5300 | file = p;
|
---|
5301 | driver_unix_convert(conn,file,&st);
|
---|
5302 | DEBUG(10,("deleting dependent file [%s]\n", file));
|
---|
5303 | unlink_internals(conn, NULL, 0, file, False);
|
---|
5304 | }
|
---|
5305 |
|
---|
5306 | i++;
|
---|
5307 | }
|
---|
5308 | }
|
---|
5309 |
|
---|
5310 | unbecome_user();
|
---|
5311 |
|
---|
5312 | return true;
|
---|
5313 | }
|
---|
5314 |
|
---|
5315 | /****************************************************************************
|
---|
5316 | Remove a printer driver from the TDB. This assumes that the the driver was
|
---|
5317 | previously looked up.
|
---|
5318 | ***************************************************************************/
|
---|
5319 |
|
---|
5320 | WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
|
---|
5321 | uint32 version, bool delete_files )
|
---|
5322 | {
|
---|
5323 | char *key = NULL;
|
---|
5324 | const char *arch;
|
---|
5325 | TDB_DATA dbuf;
|
---|
5326 | NT_PRINTER_DRIVER_INFO_LEVEL ctr;
|
---|
5327 |
|
---|
5328 | /* delete the tdb data first */
|
---|
5329 |
|
---|
5330 | arch = get_short_archi(info_3->environment);
|
---|
5331 | if (!arch) {
|
---|
5332 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
5333 | }
|
---|
5334 | if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
|
---|
5335 | arch, version, info_3->name) < 0) {
|
---|
5336 | return WERR_NOMEM;
|
---|
5337 | }
|
---|
5338 |
|
---|
5339 | DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
|
---|
5340 | key, delete_files ? "TRUE" : "FALSE" ));
|
---|
5341 |
|
---|
5342 | ctr.info_3 = info_3;
|
---|
5343 | dump_a_printer_driver( ctr, 3 );
|
---|
5344 |
|
---|
5345 | /* check if the driver actually exists for this environment */
|
---|
5346 |
|
---|
5347 | dbuf = tdb_fetch_bystring( tdb_drivers, key );
|
---|
5348 | if ( !dbuf.dptr ) {
|
---|
5349 | DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
|
---|
5350 | SAFE_FREE(key);
|
---|
5351 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
---|
5352 | }
|
---|
5353 |
|
---|
5354 | SAFE_FREE( dbuf.dptr );
|
---|
5355 |
|
---|
5356 | /* ok... the driver exists so the delete should return success */
|
---|
5357 |
|
---|
5358 | if (tdb_delete_bystring(tdb_drivers, key) == -1) {
|
---|
5359 | DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
|
---|
5360 | SAFE_FREE(key);
|
---|
5361 | return WERR_ACCESS_DENIED;
|
---|
5362 | }
|
---|
5363 |
|
---|
5364 | /*
|
---|
5365 | * now delete any associated files if delete_files == True
|
---|
5366 | * even if this part failes, we return succes because the
|
---|
5367 | * driver doesn not exist any more
|
---|
5368 | */
|
---|
5369 |
|
---|
5370 | if ( delete_files )
|
---|
5371 | delete_driver_files( info_3, user );
|
---|
5372 |
|
---|
5373 | DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
|
---|
5374 | SAFE_FREE(key);
|
---|
5375 |
|
---|
5376 | return WERR_OK;
|
---|
5377 | }
|
---|
5378 |
|
---|
5379 | /****************************************************************************
|
---|
5380 | Store a security desc for a printer.
|
---|
5381 | ****************************************************************************/
|
---|
5382 |
|
---|
5383 | WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
|
---|
5384 | {
|
---|
5385 | SEC_DESC_BUF *new_secdesc_ctr = NULL;
|
---|
5386 | SEC_DESC_BUF *old_secdesc_ctr = NULL;
|
---|
5387 | prs_struct ps;
|
---|
5388 | bool prs_init_done = false;
|
---|
5389 | TALLOC_CTX *mem_ctx = NULL;
|
---|
5390 | TDB_DATA kbuf;
|
---|
5391 | WERROR status;
|
---|
5392 |
|
---|
5393 | mem_ctx = talloc_init("nt_printing_setsec");
|
---|
5394 | if (mem_ctx == NULL)
|
---|
5395 | return WERR_NOMEM;
|
---|
5396 |
|
---|
5397 | /* The old owner and group sids of the security descriptor are not
|
---|
5398 | present when new ACEs are added or removed by changing printer
|
---|
5399 | permissions through NT. If they are NULL in the new security
|
---|
5400 | descriptor then copy them over from the old one. */
|
---|
5401 |
|
---|
5402 | if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
|
---|
5403 | DOM_SID *owner_sid, *group_sid;
|
---|
5404 | SEC_ACL *dacl, *sacl;
|
---|
5405 | SEC_DESC *psd = NULL;
|
---|
5406 | size_t size;
|
---|
5407 |
|
---|
5408 | if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
|
---|
5409 | status = WERR_NOMEM;
|
---|
5410 | goto out;
|
---|
5411 | }
|
---|
5412 |
|
---|
5413 | /* Pick out correct owner and group sids */
|
---|
5414 |
|
---|
5415 | owner_sid = secdesc_ctr->sd->owner_sid ?
|
---|
5416 | secdesc_ctr->sd->owner_sid :
|
---|
5417 | old_secdesc_ctr->sd->owner_sid;
|
---|
5418 |
|
---|
5419 | group_sid = secdesc_ctr->sd->group_sid ?
|
---|
5420 | secdesc_ctr->sd->group_sid :
|
---|
5421 | old_secdesc_ctr->sd->group_sid;
|
---|
5422 |
|
---|
5423 | dacl = secdesc_ctr->sd->dacl ?
|
---|
5424 | secdesc_ctr->sd->dacl :
|
---|
5425 | old_secdesc_ctr->sd->dacl;
|
---|
5426 |
|
---|
5427 | sacl = secdesc_ctr->sd->sacl ?
|
---|
5428 | secdesc_ctr->sd->sacl :
|
---|
5429 | old_secdesc_ctr->sd->sacl;
|
---|
5430 |
|
---|
5431 | /* Make a deep copy of the security descriptor */
|
---|
5432 |
|
---|
5433 | psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
|
---|
5434 | owner_sid, group_sid,
|
---|
5435 | sacl,
|
---|
5436 | dacl,
|
---|
5437 | &size);
|
---|
5438 |
|
---|
5439 | if (!psd) {
|
---|
5440 | status = WERR_NOMEM;
|
---|
5441 | goto out;
|
---|
5442 | }
|
---|
5443 |
|
---|
5444 | new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
|
---|
5445 | }
|
---|
5446 |
|
---|
5447 | if (!new_secdesc_ctr) {
|
---|
5448 | new_secdesc_ctr = secdesc_ctr;
|
---|
5449 | }
|
---|
5450 |
|
---|
5451 | /* Store the security descriptor in a tdb */
|
---|
5452 |
|
---|
5453 | if (!prs_init(&ps,
|
---|
5454 | (uint32)ndr_size_security_descriptor(new_secdesc_ctr->sd, 0)
|
---|
5455 | + sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL) ) {
|
---|
5456 | status = WERR_NOMEM;
|
---|
5457 | goto out;
|
---|
5458 | }
|
---|
5459 |
|
---|
5460 |
|
---|
5461 | prs_init_done = true;
|
---|
5462 |
|
---|
5463 | if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
|
---|
5464 | &ps, 1)) {
|
---|
5465 | status = WERR_BADFUNC;
|
---|
5466 | goto out;
|
---|
5467 | }
|
---|
5468 |
|
---|
5469 | kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
|
---|
5470 |
|
---|
5471 | if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
|
---|
5472 | status = WERR_OK;
|
---|
5473 | } else {
|
---|
5474 | DEBUG(1,("Failed to store secdesc for %s\n", sharename));
|
---|
5475 | status = WERR_BADFUNC;
|
---|
5476 | }
|
---|
5477 |
|
---|
5478 | /* Free malloc'ed memory */
|
---|
5479 |
|
---|
5480 | out:
|
---|
5481 |
|
---|
5482 | if (prs_init_done) {
|
---|
5483 | prs_mem_free(&ps);
|
---|
5484 | }
|
---|
5485 | if (mem_ctx)
|
---|
5486 | talloc_destroy(mem_ctx);
|
---|
5487 | return status;
|
---|
5488 | }
|
---|
5489 |
|
---|
5490 | /****************************************************************************
|
---|
5491 | Construct a default security descriptor buffer for a printer.
|
---|
5492 | ****************************************************************************/
|
---|
5493 |
|
---|
5494 | static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
|
---|
5495 | {
|
---|
5496 | SEC_ACE ace[5]; /* max number of ace entries */
|
---|
5497 | int i = 0;
|
---|
5498 | uint32_t sa;
|
---|
5499 | SEC_ACL *psa = NULL;
|
---|
5500 | SEC_DESC_BUF *sdb = NULL;
|
---|
5501 | SEC_DESC *psd = NULL;
|
---|
5502 | DOM_SID adm_sid;
|
---|
5503 | size_t sd_size;
|
---|
5504 |
|
---|
5505 | /* Create an ACE where Everyone is allowed to print */
|
---|
5506 |
|
---|
5507 | sa = PRINTER_ACE_PRINT;
|
---|
5508 | init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
|
---|
5509 | sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
|
---|
5510 |
|
---|
5511 | /* Add the domain admins group if we are a DC */
|
---|
5512 |
|
---|
5513 | if ( IS_DC ) {
|
---|
5514 | DOM_SID domadmins_sid;
|
---|
5515 |
|
---|
5516 | sid_copy(&domadmins_sid, get_global_sam_sid());
|
---|
5517 | sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
|
---|
5518 |
|
---|
5519 | sa = PRINTER_ACE_FULL_CONTROL;
|
---|
5520 | init_sec_ace(&ace[i++], &domadmins_sid,
|
---|
5521 | SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
|
---|
5522 | SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
|
---|
5523 | init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
|
---|
5524 | sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
|
---|
5525 | }
|
---|
5526 | else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
|
---|
5527 | sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
|
---|
5528 |
|
---|
5529 | sa = PRINTER_ACE_FULL_CONTROL;
|
---|
5530 | init_sec_ace(&ace[i++], &adm_sid,
|
---|
5531 | SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
|
---|
5532 | SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
|
---|
5533 | init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
|
---|
5534 | sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
|
---|
5535 | }
|
---|
5536 |
|
---|
5537 | /* add BUILTIN\Administrators as FULL CONTROL */
|
---|
5538 |
|
---|
5539 | sa = PRINTER_ACE_FULL_CONTROL;
|
---|
5540 | init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
|
---|
5541 | SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
|
---|
5542 | SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
|
---|
5543 | init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
|
---|
5544 | SEC_ACE_TYPE_ACCESS_ALLOWED,
|
---|
5545 | sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
|
---|
5546 |
|
---|
5547 | /* Make the security descriptor owned by the BUILTIN\Administrators */
|
---|
5548 |
|
---|
5549 | /* The ACL revision number in rpc_secdesc.h differs from the one
|
---|
5550 | created by NT when setting ACE entries in printer
|
---|
5551 | descriptors. NT4 complains about the property being edited by a
|
---|
5552 | NT5 machine. */
|
---|
5553 |
|
---|
5554 | if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
|
---|
5555 | psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
|
---|
5556 | &global_sid_Builtin_Administrators,
|
---|
5557 | &global_sid_Builtin_Administrators,
|
---|
5558 | NULL, psa, &sd_size);
|
---|
5559 | }
|
---|
5560 |
|
---|
5561 | if (!psd) {
|
---|
5562 | DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
|
---|
5563 | return NULL;
|
---|
5564 | }
|
---|
5565 |
|
---|
5566 | sdb = make_sec_desc_buf(ctx, sd_size, psd);
|
---|
5567 |
|
---|
5568 | DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
|
---|
5569 | (unsigned int)sd_size));
|
---|
5570 |
|
---|
5571 | return sdb;
|
---|
5572 | }
|
---|
5573 |
|
---|
5574 | /****************************************************************************
|
---|
5575 | Get a security desc for a printer.
|
---|
5576 | ****************************************************************************/
|
---|
5577 |
|
---|
5578 | bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
|
---|
5579 | {
|
---|
5580 | prs_struct ps;
|
---|
5581 | TDB_DATA kbuf;
|
---|
5582 | char *temp;
|
---|
5583 |
|
---|
5584 | if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
|
---|
5585 | sharename = temp + 1;
|
---|
5586 | }
|
---|
5587 |
|
---|
5588 | ZERO_STRUCT(ps);
|
---|
5589 |
|
---|
5590 | /* Fetch security descriptor from tdb */
|
---|
5591 |
|
---|
5592 | kbuf = make_printers_secdesc_tdbkey(ctx, sharename );
|
---|
5593 |
|
---|
5594 | if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
|
---|
5595 | !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
|
---|
5596 |
|
---|
5597 | prs_mem_free(&ps);
|
---|
5598 |
|
---|
5599 | DEBUG(4,("using default secdesc for %s\n", sharename));
|
---|
5600 |
|
---|
5601 | if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
|
---|
5602 | return False;
|
---|
5603 | }
|
---|
5604 |
|
---|
5605 | /* Save default security descriptor for later */
|
---|
5606 |
|
---|
5607 | if (!prs_init(&ps, (uint32)ndr_size_security_descriptor((*secdesc_ctr)->sd, 0) +
|
---|
5608 | sizeof(SEC_DESC_BUF), ctx, MARSHALL))
|
---|
5609 | return False;
|
---|
5610 |
|
---|
5611 | if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
|
---|
5612 | tdb_prs_store(tdb_printers, kbuf, &ps);
|
---|
5613 | }
|
---|
5614 |
|
---|
5615 | prs_mem_free(&ps);
|
---|
5616 |
|
---|
5617 | return True;
|
---|
5618 | }
|
---|
5619 |
|
---|
5620 | prs_mem_free(&ps);
|
---|
5621 |
|
---|
5622 | /* If security descriptor is owned by S-1-1-0 and winbindd is up,
|
---|
5623 | this security descriptor has been created when winbindd was
|
---|
5624 | down. Take ownership of security descriptor. */
|
---|
5625 |
|
---|
5626 | if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
|
---|
5627 | DOM_SID owner_sid;
|
---|
5628 |
|
---|
5629 | /* Change sd owner to workgroup administrator */
|
---|
5630 |
|
---|
5631 | if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
|
---|
5632 | SEC_DESC_BUF *new_secdesc_ctr = NULL;
|
---|
5633 | SEC_DESC *psd = NULL;
|
---|
5634 | size_t size;
|
---|
5635 |
|
---|
5636 | /* Create new sd */
|
---|
5637 |
|
---|
5638 | sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
|
---|
5639 |
|
---|
5640 | psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
|
---|
5641 | &owner_sid,
|
---|
5642 | (*secdesc_ctr)->sd->group_sid,
|
---|
5643 | (*secdesc_ctr)->sd->sacl,
|
---|
5644 | (*secdesc_ctr)->sd->dacl,
|
---|
5645 | &size);
|
---|
5646 |
|
---|
5647 | if (!psd) {
|
---|
5648 | return False;
|
---|
5649 | }
|
---|
5650 |
|
---|
5651 | new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
|
---|
5652 | if (!new_secdesc_ctr) {
|
---|
5653 | return False;
|
---|
5654 | }
|
---|
5655 |
|
---|
5656 | /* Swap with other one */
|
---|
5657 |
|
---|
5658 | *secdesc_ctr = new_secdesc_ctr;
|
---|
5659 |
|
---|
5660 | /* Set it */
|
---|
5661 |
|
---|
5662 | nt_printing_setsec(sharename, *secdesc_ctr);
|
---|
5663 | }
|
---|
5664 | }
|
---|
5665 |
|
---|
5666 | if (DEBUGLEVEL >= 10) {
|
---|
5667 | SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
|
---|
5668 | int i;
|
---|
5669 |
|
---|
5670 | DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
|
---|
5671 | sharename, the_acl->num_aces));
|
---|
5672 |
|
---|
5673 | for (i = 0; i < the_acl->num_aces; i++) {
|
---|
5674 | DEBUG(10, ("%s %d %d 0x%08x\n",
|
---|
5675 | sid_string_dbg(&the_acl->aces[i].trustee),
|
---|
5676 | the_acl->aces[i].type, the_acl->aces[i].flags,
|
---|
5677 | the_acl->aces[i].access_mask));
|
---|
5678 | }
|
---|
5679 | }
|
---|
5680 |
|
---|
5681 | return True;
|
---|
5682 | }
|
---|
5683 |
|
---|
5684 | /* error code:
|
---|
5685 | 0: everything OK
|
---|
5686 | 1: level not implemented
|
---|
5687 | 2: file doesn't exist
|
---|
5688 | 3: can't allocate memory
|
---|
5689 | 4: can't free memory
|
---|
5690 | 5: non existant struct
|
---|
5691 | */
|
---|
5692 |
|
---|
5693 | /*
|
---|
5694 | A printer and a printer driver are 2 different things.
|
---|
5695 | NT manages them separatelly, Samba does the same.
|
---|
5696 | Why ? Simply because it's easier and it makes sense !
|
---|
5697 |
|
---|
5698 | Now explanation: You have 3 printers behind your samba server,
|
---|
5699 | 2 of them are the same make and model (laser A and B). But laser B
|
---|
5700 | has an 3000 sheet feeder and laser A doesn't such an option.
|
---|
5701 | Your third printer is an old dot-matrix model for the accounting :-).
|
---|
5702 |
|
---|
5703 | If the /usr/local/samba/lib directory (default dir), you will have
|
---|
5704 | 5 files to describe all of this.
|
---|
5705 |
|
---|
5706 | 3 files for the printers (1 by printer):
|
---|
5707 | NTprinter_laser A
|
---|
5708 | NTprinter_laser B
|
---|
5709 | NTprinter_accounting
|
---|
5710 | 2 files for the drivers (1 for the laser and 1 for the dot matrix)
|
---|
5711 | NTdriver_printer model X
|
---|
5712 | NTdriver_printer model Y
|
---|
5713 |
|
---|
5714 | jfm: I should use this comment for the text file to explain
|
---|
5715 | same thing for the forms BTW.
|
---|
5716 | Je devrais mettre mes commentaires en francais, ca serait mieux :-)
|
---|
5717 |
|
---|
5718 | */
|
---|
5719 |
|
---|
5720 | /* Convert generic access rights to printer object specific access rights.
|
---|
5721 | It turns out that NT4 security descriptors use generic access rights and
|
---|
5722 | NT5 the object specific ones. */
|
---|
5723 |
|
---|
5724 | void map_printer_permissions(SEC_DESC *sd)
|
---|
5725 | {
|
---|
5726 | int i;
|
---|
5727 |
|
---|
5728 | for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
|
---|
5729 | se_map_generic(&sd->dacl->aces[i].access_mask,
|
---|
5730 | &printer_generic_mapping);
|
---|
5731 | }
|
---|
5732 | }
|
---|
5733 |
|
---|
5734 | void map_job_permissions(SEC_DESC *sd)
|
---|
5735 | {
|
---|
5736 | int i;
|
---|
5737 |
|
---|
5738 | for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
|
---|
5739 | se_map_generic(&sd->dacl->aces[i].access_mask,
|
---|
5740 | &job_generic_mapping);
|
---|
5741 | }
|
---|
5742 | }
|
---|
5743 |
|
---|
5744 |
|
---|
5745 | /****************************************************************************
|
---|
5746 | Check a user has permissions to perform the given operation. We use the
|
---|
5747 | permission constants defined in include/rpc_spoolss.h to check the various
|
---|
5748 | actions we perform when checking printer access.
|
---|
5749 |
|
---|
5750 | PRINTER_ACCESS_ADMINISTER:
|
---|
5751 | print_queue_pause, print_queue_resume, update_printer_sec,
|
---|
5752 | update_printer, spoolss_addprinterex_level_2,
|
---|
5753 | _spoolss_setprinterdata
|
---|
5754 |
|
---|
5755 | PRINTER_ACCESS_USE:
|
---|
5756 | print_job_start
|
---|
5757 |
|
---|
5758 | JOB_ACCESS_ADMINISTER:
|
---|
5759 | print_job_delete, print_job_pause, print_job_resume,
|
---|
5760 | print_queue_purge
|
---|
5761 |
|
---|
5762 | Try access control in the following order (for performance reasons):
|
---|
5763 | 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
|
---|
5764 | 2) check security descriptor (bit comparisons in memory)
|
---|
5765 | 3) "printer admins" (may result in numerous calls to winbind)
|
---|
5766 |
|
---|
5767 | ****************************************************************************/
|
---|
5768 | bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
|
---|
5769 | int access_type)
|
---|
5770 | {
|
---|
5771 | SEC_DESC_BUF *secdesc = NULL;
|
---|
5772 | uint32 access_granted;
|
---|
5773 | NTSTATUS status;
|
---|
5774 | const char *pname;
|
---|
5775 | TALLOC_CTX *mem_ctx = NULL;
|
---|
5776 | SE_PRIV se_printop = SE_PRINT_OPERATOR;
|
---|
5777 |
|
---|
5778 | /* If user is NULL then use the current_user structure */
|
---|
5779 |
|
---|
5780 | /* Always allow root or SE_PRINT_OPERATROR to do anything */
|
---|
5781 |
|
---|
5782 | if (server_info->utok.uid == 0
|
---|
5783 | || user_has_privileges(server_info->ptok, &se_printop ) ) {
|
---|
5784 | return True;
|
---|
5785 | }
|
---|
5786 |
|
---|
5787 | /* Get printer name */
|
---|
5788 |
|
---|
5789 | pname = PRINTERNAME(snum);
|
---|
5790 |
|
---|
5791 | if (!pname || !*pname) {
|
---|
5792 | errno = EACCES;
|
---|
5793 | return False;
|
---|
5794 | }
|
---|
5795 |
|
---|
5796 | /* Get printer security descriptor */
|
---|
5797 |
|
---|
5798 | if(!(mem_ctx = talloc_init("print_access_check"))) {
|
---|
5799 | errno = ENOMEM;
|
---|
5800 | return False;
|
---|
5801 | }
|
---|
5802 |
|
---|
5803 | if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
|
---|
5804 | talloc_destroy(mem_ctx);
|
---|
5805 | errno = ENOMEM;
|
---|
5806 | return False;
|
---|
5807 | }
|
---|
5808 |
|
---|
5809 | if (access_type == JOB_ACCESS_ADMINISTER) {
|
---|
5810 | SEC_DESC_BUF *parent_secdesc = secdesc;
|
---|
5811 |
|
---|
5812 | /* Create a child security descriptor to check permissions
|
---|
5813 | against. This is because print jobs are child objects
|
---|
5814 | objects of a printer. */
|
---|
5815 |
|
---|
5816 | status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
|
---|
5817 |
|
---|
5818 | if (!NT_STATUS_IS_OK(status)) {
|
---|
5819 | talloc_destroy(mem_ctx);
|
---|
5820 | errno = map_errno_from_nt_status(status);
|
---|
5821 | return False;
|
---|
5822 | }
|
---|
5823 |
|
---|
5824 | map_job_permissions(secdesc->sd);
|
---|
5825 | } else {
|
---|
5826 | map_printer_permissions(secdesc->sd);
|
---|
5827 | }
|
---|
5828 |
|
---|
5829 | /* Check access */
|
---|
5830 | status = se_access_check(secdesc->sd, server_info->ptok, access_type,
|
---|
5831 | &access_granted);
|
---|
5832 |
|
---|
5833 | DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
|
---|
5834 |
|
---|
5835 | /* see if we need to try the printer admin list */
|
---|
5836 |
|
---|
5837 | if ((access_granted == 0) &&
|
---|
5838 | (token_contains_name_in_list(uidtoname(server_info->utok.uid),
|
---|
5839 | NULL, NULL, server_info->ptok,
|
---|
5840 | lp_printer_admin(snum)))) {
|
---|
5841 | talloc_destroy(mem_ctx);
|
---|
5842 | return True;
|
---|
5843 | }
|
---|
5844 |
|
---|
5845 | talloc_destroy(mem_ctx);
|
---|
5846 |
|
---|
5847 | if (!NT_STATUS_IS_OK(status)) {
|
---|
5848 | errno = EACCES;
|
---|
5849 | }
|
---|
5850 |
|
---|
5851 | return NT_STATUS_IS_OK(status);
|
---|
5852 | }
|
---|
5853 |
|
---|
5854 | /****************************************************************************
|
---|
5855 | Check the time parameters allow a print operation.
|
---|
5856 | *****************************************************************************/
|
---|
5857 |
|
---|
5858 | bool print_time_access_check(const char *servicename)
|
---|
5859 | {
|
---|
5860 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
---|
5861 | bool ok = False;
|
---|
5862 | time_t now = time(NULL);
|
---|
5863 | struct tm *t;
|
---|
5864 | uint32 mins;
|
---|
5865 |
|
---|
5866 | if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
|
---|
5867 | return False;
|
---|
5868 |
|
---|
5869 | if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
|
---|
5870 | ok = True;
|
---|
5871 |
|
---|
5872 | t = gmtime(&now);
|
---|
5873 | mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
|
---|
5874 |
|
---|
5875 | if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
|
---|
5876 | ok = True;
|
---|
5877 |
|
---|
5878 | free_a_printer(&printer, 2);
|
---|
5879 |
|
---|
5880 | if (!ok)
|
---|
5881 | errno = EACCES;
|
---|
5882 |
|
---|
5883 | return ok;
|
---|
5884 | }
|
---|
5885 |
|
---|
5886 | /****************************************************************************
|
---|
5887 | Fill in the servername sent in the _spoolss_open_printer_ex() call
|
---|
5888 | ****************************************************************************/
|
---|
5889 |
|
---|
5890 | char* get_server_name( Printer_entry *printer )
|
---|
5891 | {
|
---|
5892 | return printer->servername;
|
---|
5893 | }
|
---|
5894 |
|
---|
5895 |
|
---|