tdb: add overflow/ENOSPC handling to tdb_expand_file()
[obnox/samba/samba-obnox.git] / source3 / printing / nt_printing_migrate.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *
5  *  Copyright (c) Andreas Schneider            2010.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22 #include "printing/nt_printing_migrate.h"
23
24 #include "rpc_client/rpc_client.h"
25 #include "librpc/gen_ndr/ndr_ntprinting.h"
26 #include "librpc/gen_ndr/ndr_spoolss_c.h"
27 #include "librpc/gen_ndr/ndr_security.h"
28 #include "rpc_client/cli_winreg_spoolss.h"
29
30 NTSTATUS printing_tdb_migrate_form(TALLOC_CTX *mem_ctx,
31                                    struct rpc_pipe_client *winreg_pipe,
32                                    const char *key_name,
33                                    unsigned char *data,
34                                    size_t length)
35 {
36         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
37         enum ndr_err_code ndr_err;
38         struct ntprinting_form r;
39         struct spoolss_AddFormInfo1 f1;
40         DATA_BLOB blob;
41         WERROR result;
42
43         blob = data_blob_const(data, length);
44
45         ZERO_STRUCT(r);
46
47         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
48                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
49         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
50                 DEBUG(2, ("Form pull failed: %s\n",
51                           ndr_errstr(ndr_err)));
52                 return NT_STATUS_NO_MEMORY;
53         }
54
55         /* Don't migrate builtin forms */
56         if (r.flag == SPOOLSS_FORM_BUILTIN) {
57                 return NT_STATUS_OK;
58         }
59
60         DEBUG(2, ("Migrating Form: %s\n", key_name));
61
62         f1.form_name = key_name;
63         f1.flags = r.flag;
64
65         f1.size.width = r.width;
66         f1.size.height = r.length;
67
68         f1.area.top = r.top;
69         f1.area.right = r.right;
70         f1.area.bottom = r.bottom;
71         f1.area.left = r.left;
72
73         result = winreg_printer_addform1(mem_ctx,
74                                          b,
75                                          &f1);
76         if (W_ERROR_EQUAL(result, WERR_FILE_EXISTS)) {
77                 /* Don't migrate form if it already exists. */
78                 result = WERR_OK;
79         }
80         if (!W_ERROR_IS_OK(result)) {
81                 return werror_to_ntstatus(result);
82         }
83
84         return NT_STATUS_OK;
85 }
86
87 NTSTATUS printing_tdb_migrate_driver(TALLOC_CTX *mem_ctx,
88                                      struct rpc_pipe_client *winreg_pipe,
89                                      const char *key_name,
90                                      unsigned char *data,
91                                      size_t length,
92                                      bool do_string_conversion)
93 {
94         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
95         enum ndr_err_code ndr_err;
96         struct ntprinting_driver r;
97         struct spoolss_AddDriverInfoCtr d;
98         struct spoolss_AddDriverInfo3 d3;
99         struct spoolss_StringArray a;
100         DATA_BLOB blob;
101         WERROR result;
102         const char *driver_name;
103         uint32_t driver_version;
104
105         blob = data_blob_const(data, length);
106
107         ZERO_STRUCT(r);
108
109         if (do_string_conversion) {
110                 r.string_flags = LIBNDR_FLAG_STR_ASCII;
111         }
112
113         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
114                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
115         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
116                 DEBUG(2, ("Driver pull failed: %s\n",
117                           ndr_errstr(ndr_err)));
118                 return NT_STATUS_NO_MEMORY;
119         }
120
121         DEBUG(2, ("Migrating Printer Driver: %s\n", key_name));
122
123         ZERO_STRUCT(d3);
124         ZERO_STRUCT(a);
125
126         a.string = r.dependent_files;
127
128         d3.architecture = r.environment;
129         d3.config_file = r.configfile;
130         d3.data_file = r.datafile;
131         d3.default_datatype = r.defaultdatatype;
132         d3.dependent_files = &a;
133         d3.driver_path = r.driverpath;
134         d3.help_file = r.helpfile;
135         d3.monitor_name = r.monitorname;
136         d3.driver_name = r.name;
137         d3.version = r.version;
138
139         d.level = 3;
140         d.info.info3 = &d3;
141
142         result = winreg_add_driver(mem_ctx,
143                                    b,
144                                    &d,
145                                    &driver_name,
146                                    &driver_version);
147         if (!W_ERROR_IS_OK(result)) {
148                 return werror_to_ntstatus(result);
149         }
150
151         return NT_STATUS_OK;
152 }
153
154 NTSTATUS printing_tdb_migrate_printer(TALLOC_CTX *mem_ctx,
155                                       struct rpc_pipe_client *winreg_pipe,
156                                       const char *key_name,
157                                       unsigned char *data,
158                                       size_t length,
159                                       bool do_string_conversion)
160 {
161         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
162         enum ndr_err_code ndr_err;
163         struct ntprinting_printer r;
164         struct spoolss_SetPrinterInfo2 info2;
165         struct spoolss_DeviceMode dm;
166         struct spoolss_DevmodeContainer devmode_ctr;
167         DATA_BLOB blob;
168         NTSTATUS status;
169         WERROR result;
170         int j;
171         uint32_t info2_mask = (SPOOLSS_PRINTER_INFO_ALL)
172                                 & ~SPOOLSS_PRINTER_INFO_SECDESC;
173
174         if (strequal(key_name, "printers")) {
175                 return NT_STATUS_OK;
176         }
177
178         blob = data_blob_const(data, length);
179
180         ZERO_STRUCT(r);
181
182         if (do_string_conversion) {
183                 r.info.string_flags = LIBNDR_FLAG_STR_ASCII;
184         }
185
186         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
187                    (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
188         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
189                 DEBUG(2, ("printer pull failed: %s\n",
190                           ndr_errstr(ndr_err)));
191                 return NT_STATUS_NO_MEMORY;
192         }
193
194         DEBUG(2, ("Migrating Printer: %s\n", key_name));
195
196         ZERO_STRUCT(devmode_ctr);
197
198         /* Create printer info level 2 */
199         ZERO_STRUCT(info2);
200
201         info2.attributes = r.info.attributes;
202         info2.averageppm = r.info.averageppm;
203         info2.cjobs = r.info.cjobs;
204         info2.comment = r.info.comment;
205         info2.datatype = r.info.datatype;
206         info2.defaultpriority = r.info.default_priority;
207         info2.drivername = r.info.drivername;
208         info2.location = r.info.location;
209         info2.parameters = r.info.parameters;
210         info2.portname = r.info.portname;
211         info2.printername = r.info.printername;
212         info2.printprocessor = r.info.printprocessor;
213         info2.priority = r.info.priority;
214         info2.sepfile = r.info.sepfile;
215         info2.sharename = r.info.sharename;
216         info2.starttime = r.info.starttime;
217         info2.status = r.info.status;
218         info2.untiltime = r.info.untiltime;
219
220         /* Create Device Mode */
221         if (r.devmode == NULL) {
222                 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
223         } else {
224                 ZERO_STRUCT(dm);
225
226                 dm.bitsperpel              = r.devmode->bitsperpel;
227                 dm.collate                 = r.devmode->collate;
228                 dm.color                   = r.devmode->color;
229                 dm.copies                  = r.devmode->copies;
230                 dm.defaultsource           = r.devmode->defaultsource;
231                 dm.devicename              = r.devmode->devicename;
232                 dm.displayflags            = r.devmode->displayflags;
233                 dm.displayfrequency        = r.devmode->displayfrequency;
234                 dm.dithertype              = r.devmode->dithertype;
235                 dm.driverversion           = r.devmode->driverversion;
236                 dm.duplex                  = r.devmode->duplex;
237                 dm.fields                  = r.devmode->fields;
238                 dm.formname                = r.devmode->formname;
239                 dm.icmintent               = r.devmode->icmintent;
240                 dm.icmmethod               = r.devmode->icmmethod;
241                 dm.logpixels               = r.devmode->logpixels;
242                 dm.mediatype               = r.devmode->mediatype;
243                 dm.orientation             = r.devmode->orientation;
244                 dm.panningheight           = r.devmode->pelsheight;
245                 dm.panningwidth            = r.devmode->panningwidth;
246                 dm.paperlength             = r.devmode->paperlength;
247                 dm.papersize               = r.devmode->papersize;
248                 dm.paperwidth              = r.devmode->paperwidth;
249                 dm.pelsheight              = r.devmode->pelsheight;
250                 dm.pelswidth               = r.devmode->pelswidth;
251                 dm.printquality            = r.devmode->printquality;
252                 dm.size                    = r.devmode->size;
253                 dm.scale                   = r.devmode->scale;
254                 dm.specversion             = r.devmode->specversion;
255                 dm.ttoption                = r.devmode->ttoption;
256                 dm.yresolution             = r.devmode->yresolution;
257
258                 if (r.devmode->nt_dev_private != NULL) {
259                         dm.driverextra_data.data   = r.devmode->nt_dev_private->data;
260                         dm.driverextra_data.length = r.devmode->nt_dev_private->length;
261                         dm.__driverextra_length    = r.devmode->nt_dev_private->length;
262                 }
263
264                 devmode_ctr.devmode = &dm;
265         }
266
267         result = winreg_update_printer(mem_ctx, b,
268                                        key_name,
269                                        info2_mask,
270                                        &info2,
271                                        &dm,
272                                        NULL);
273         if (!W_ERROR_IS_OK(result)) {
274                 DEBUG(2, ("SetPrinter(%s) level 2 refused -- %s.\n",
275                           key_name, win_errstr(result)));
276                 status = werror_to_ntstatus(result);
277                 goto done;
278         }
279
280         /* migrate printerdata */
281         for (j = 0; j < r.count; j++) {
282                 char *valuename;
283                 const char *keyname;
284
285                 if (r.printer_data[j].type == REG_NONE) {
286                         continue;
287                 }
288
289                 keyname = r.printer_data[j].name;
290                 valuename = strchr(keyname, '\\');
291                 if (valuename == NULL) {
292                         continue;
293                 } else {
294                         valuename[0] = '\0';
295                         valuename++;
296                 }
297
298                 result = winreg_set_printer_dataex(mem_ctx, b,
299                                                    key_name,
300                                                    keyname,
301                                                    valuename,
302                                                    r.printer_data[j].type,
303                                                    r.printer_data[j].data.data,
304                                                    r.printer_data[j].data.length);
305                 if (!W_ERROR_IS_OK(result)) {
306                         DEBUG(2, ("SetPrinterDataEx: printer [%s], keyname [%s], "
307                                   "valuename [%s] refused -- %s.\n",
308                                   key_name, keyname, valuename,
309                                   win_errstr(result)));
310                         status = werror_to_ntstatus(result);
311                         break;
312                 }
313         }
314
315         status = NT_STATUS_OK;
316  done:
317
318         return status;
319 }
320
321 NTSTATUS printing_tdb_migrate_secdesc(TALLOC_CTX *mem_ctx,
322                                       struct rpc_pipe_client *winreg_pipe,
323                                       const char *key_name,
324                                       unsigned char *data,
325                                       size_t length)
326 {
327         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
328         enum ndr_err_code ndr_err;
329         struct sec_desc_buf secdesc_ctr;
330         DATA_BLOB blob;
331         WERROR result;
332
333         if (strequal(key_name, "printers")) {
334                 return NT_STATUS_OK;
335         }
336
337         blob = data_blob_const(data, length);
338
339         ZERO_STRUCT(secdesc_ctr);
340
341         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
342                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
343         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
344                 DEBUG(2, ("security descriptor pull failed: %s\n",
345                           ndr_errstr(ndr_err)));
346                 return NT_STATUS_NO_MEMORY;
347         }
348
349         DEBUG(2, ("Migrating Security Descriptor: %s\n", key_name));
350
351         result = winreg_set_printer_secdesc(mem_ctx, b,
352                                             key_name,
353                                             secdesc_ctr.sd);
354         if (!W_ERROR_IS_OK(result)) {
355                 return werror_to_ntstatus(result);
356         }
357
358         return NT_STATUS_OK;
359 }