lib: Give lib/util/util_file.c its own header file
[samba.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  *  Copyright (C) Bjoern Baumbach <bb@sernet.de> 2011
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 #include "printing/nt_printing_migrate.h"
24
25 #include "rpc_client/rpc_client.h"
26 #include "librpc/gen_ndr/ndr_ntprinting.h"
27 #include "librpc/gen_ndr/ndr_spoolss_c.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "rpc_client/cli_winreg_spoolss.h"
30
31 static const char *driver_file_basename(const char *file)
32 {
33         const char *basefile;
34
35         basefile = strrchr(file, '\\');
36         if (basefile == NULL) {
37                 basefile = file;
38         } else {
39                 basefile++;
40         }
41
42         return basefile;
43 }
44
45 NTSTATUS printing_tdb_migrate_form(TALLOC_CTX *mem_ctx,
46                                    struct rpc_pipe_client *winreg_pipe,
47                                    const char *key_name,
48                                    unsigned char *data,
49                                    size_t length)
50 {
51         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
52         enum ndr_err_code ndr_err;
53         struct ntprinting_form r;
54         struct spoolss_AddFormInfo1 f1;
55         DATA_BLOB blob;
56         WERROR result;
57
58         blob = data_blob_const(data, length);
59
60         ZERO_STRUCT(r);
61
62         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
63                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
64         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
65                 DEBUG(2, ("Form pull failed: %s\n",
66                           ndr_errstr(ndr_err)));
67                 return NT_STATUS_NO_MEMORY;
68         }
69
70         /* Don't migrate builtin forms */
71         if (r.flag == SPOOLSS_FORM_BUILTIN) {
72                 return NT_STATUS_OK;
73         }
74
75         DEBUG(2, ("Migrating Form: %s\n", key_name));
76
77         f1.form_name = key_name;
78         f1.flags = r.flag;
79
80         f1.size.width = r.width;
81         f1.size.height = r.length;
82
83         f1.area.top = r.top;
84         f1.area.right = r.right;
85         f1.area.bottom = r.bottom;
86         f1.area.left = r.left;
87
88         result = winreg_printer_addform1(mem_ctx,
89                                          b,
90                                          &f1);
91         if (W_ERROR_EQUAL(result, WERR_FILE_EXISTS)) {
92                 /* Don't migrate form if it already exists. */
93                 result = WERR_OK;
94         }
95         if (!W_ERROR_IS_OK(result)) {
96                 return werror_to_ntstatus(result);
97         }
98
99         return NT_STATUS_OK;
100 }
101
102 NTSTATUS printing_tdb_migrate_driver(TALLOC_CTX *mem_ctx,
103                                      struct rpc_pipe_client *winreg_pipe,
104                                      const char *key_name,
105                                      unsigned char *data,
106                                      size_t length,
107                                      bool do_string_conversion)
108 {
109         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
110         enum ndr_err_code ndr_err;
111         struct ntprinting_driver r;
112         struct spoolss_AddDriverInfoCtr d;
113         struct spoolss_AddDriverInfo3 d3;
114         struct spoolss_StringArray a;
115         DATA_BLOB blob;
116         WERROR result;
117         const char *driver_name;
118         uint32_t driver_version;
119         int i;
120
121         blob = data_blob_const(data, length);
122
123         ZERO_STRUCT(r);
124
125         if (do_string_conversion) {
126                 r.string_flags = LIBNDR_FLAG_STR_ASCII;
127         }
128
129         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
130                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
131         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
132                 DEBUG(2, ("Driver pull failed: %s\n",
133                           ndr_errstr(ndr_err)));
134                 return NT_STATUS_NO_MEMORY;
135         }
136
137         DEBUG(2, ("Migrating Printer Driver: %s\n", key_name));
138
139         ZERO_STRUCT(d3);
140         ZERO_STRUCT(a);
141
142         /* remove paths from file names */
143         if (r.dependent_files != NULL) {
144                 for (i = 0 ; r.dependent_files[i] != NULL; i++) {
145                         r.dependent_files[i] = driver_file_basename(r.dependent_files[i]);
146                 }
147         }
148         a.string = r.dependent_files;
149
150         r.driverpath = driver_file_basename(r.driverpath);
151         r.configfile = driver_file_basename(r.configfile);
152         r.datafile = driver_file_basename(r.datafile);
153         r.helpfile = driver_file_basename(r.helpfile);
154
155         d3.architecture = r.environment;
156         d3.config_file = r.configfile;
157         d3.data_file = r.datafile;
158         d3.default_datatype = r.defaultdatatype;
159         d3.dependent_files = &a;
160         d3.driver_path = r.driverpath;
161         d3.help_file = r.helpfile;
162         d3.monitor_name = r.monitorname;
163         d3.driver_name = r.name;
164         d3.version = r.version;
165
166         d.level = 3;
167         d.info.info3 = &d3;
168
169         result = winreg_add_driver(mem_ctx,
170                                    b,
171                                    &d,
172                                    &driver_name,
173                                    &driver_version);
174         if (!W_ERROR_IS_OK(result)) {
175                 return werror_to_ntstatus(result);
176         }
177
178         return NT_STATUS_OK;
179 }
180
181 NTSTATUS printing_tdb_migrate_printer(TALLOC_CTX *mem_ctx,
182                                       struct rpc_pipe_client *winreg_pipe,
183                                       const char *key_name,
184                                       unsigned char *data,
185                                       size_t length,
186                                       bool do_string_conversion)
187 {
188         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
189         enum ndr_err_code ndr_err;
190         struct ntprinting_printer r;
191         struct spoolss_SetPrinterInfo2 info2;
192         struct spoolss_DeviceMode dm;
193         struct spoolss_DevmodeContainer devmode_ctr;
194         DATA_BLOB blob;
195         NTSTATUS status;
196         WERROR result;
197         int j;
198         uint32_t info2_mask = (SPOOLSS_PRINTER_INFO_ALL)
199                                 & ~SPOOLSS_PRINTER_INFO_SECDESC;
200
201         if (strequal(key_name, "printers")) {
202                 return NT_STATUS_OK;
203         }
204
205         blob = data_blob_const(data, length);
206
207         ZERO_STRUCT(r);
208
209         if (do_string_conversion) {
210                 r.info.string_flags = LIBNDR_FLAG_STR_ASCII;
211         }
212
213         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
214                    (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
215         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
216                 DEBUG(2, ("printer pull failed: %s\n",
217                           ndr_errstr(ndr_err)));
218                 return NT_STATUS_NO_MEMORY;
219         }
220
221         DEBUG(2, ("Migrating Printer: %s\n", key_name));
222
223         ZERO_STRUCT(devmode_ctr);
224
225         /* Create printer info level 2 */
226         ZERO_STRUCT(info2);
227
228         info2.attributes = r.info.attributes;
229         info2.averageppm = r.info.averageppm;
230         info2.cjobs = r.info.cjobs;
231         info2.comment = r.info.comment;
232         info2.datatype = r.info.datatype;
233         info2.defaultpriority = r.info.default_priority;
234         info2.drivername = r.info.drivername;
235         info2.location = r.info.location;
236         info2.parameters = r.info.parameters;
237         info2.portname = r.info.portname;
238         info2.printername = r.info.printername;
239         info2.printprocessor = r.info.printprocessor;
240         info2.priority = r.info.priority;
241         info2.sepfile = r.info.sepfile;
242         info2.sharename = r.info.sharename;
243         info2.starttime = r.info.starttime;
244         info2.status = r.info.status;
245         info2.untiltime = r.info.untiltime;
246
247         /* Create Device Mode */
248         if (r.devmode == NULL) {
249                 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
250         } else {
251                 ZERO_STRUCT(dm);
252
253                 dm.bitsperpel              = r.devmode->bitsperpel;
254                 dm.collate                 = r.devmode->collate;
255                 dm.color                   = r.devmode->color;
256                 dm.copies                  = r.devmode->copies;
257                 dm.defaultsource           = r.devmode->defaultsource;
258                 dm.devicename              = r.devmode->devicename;
259                 dm.displayflags            = r.devmode->displayflags;
260                 dm.displayfrequency        = r.devmode->displayfrequency;
261                 dm.dithertype              = r.devmode->dithertype;
262                 dm.driverversion           = r.devmode->driverversion;
263                 dm.duplex                  = r.devmode->duplex;
264                 dm.fields                  = r.devmode->fields;
265                 dm.formname                = r.devmode->formname;
266                 dm.icmintent               = r.devmode->icmintent;
267                 dm.icmmethod               = r.devmode->icmmethod;
268                 dm.logpixels               = r.devmode->logpixels;
269                 dm.mediatype               = r.devmode->mediatype;
270                 dm.orientation             = r.devmode->orientation;
271                 dm.panningheight           = r.devmode->pelsheight;
272                 dm.panningwidth            = r.devmode->panningwidth;
273                 dm.paperlength             = r.devmode->paperlength;
274                 dm.papersize               = r.devmode->papersize;
275                 dm.paperwidth              = r.devmode->paperwidth;
276                 dm.pelsheight              = r.devmode->pelsheight;
277                 dm.pelswidth               = r.devmode->pelswidth;
278                 dm.printquality            = r.devmode->printquality;
279                 dm.size                    = r.devmode->size;
280                 dm.scale                   = r.devmode->scale;
281                 dm.specversion             = r.devmode->specversion;
282                 dm.ttoption                = r.devmode->ttoption;
283                 dm.yresolution             = r.devmode->yresolution;
284
285                 if (r.devmode->nt_dev_private != NULL) {
286                         dm.driverextra_data.data   = r.devmode->nt_dev_private->data;
287                         dm.driverextra_data.length = r.devmode->nt_dev_private->length;
288                         dm.__driverextra_length    = r.devmode->nt_dev_private->length;
289                 }
290
291                 devmode_ctr.devmode = &dm;
292         }
293
294         result = winreg_update_printer(mem_ctx, b,
295                                        key_name,
296                                        info2_mask,
297                                        &info2,
298                                        &dm,
299                                        NULL);
300         if (!W_ERROR_IS_OK(result)) {
301                 DEBUG(2, ("SetPrinter(%s) level 2 refused -- %s.\n",
302                           key_name, win_errstr(result)));
303                 status = werror_to_ntstatus(result);
304                 goto done;
305         }
306
307         /* migrate printerdata */
308         for (j = 0; j < r.count; j++) {
309                 char *valuename;
310                 const char *keyname;
311
312                 if (r.printer_data[j].type == REG_NONE) {
313                         continue;
314                 }
315
316                 keyname = r.printer_data[j].name;
317                 valuename = strchr(keyname, '\\');
318                 if (valuename == NULL) {
319                         continue;
320                 } else {
321                         valuename[0] = '\0';
322                         valuename++;
323                 }
324
325                 result = winreg_set_printer_dataex(mem_ctx, b,
326                                                    key_name,
327                                                    keyname,
328                                                    valuename,
329                                                    r.printer_data[j].type,
330                                                    r.printer_data[j].data.data,
331                                                    r.printer_data[j].data.length);
332                 if (!W_ERROR_IS_OK(result)) {
333                         DEBUG(2, ("SetPrinterDataEx: printer [%s], keyname [%s], "
334                                   "valuename [%s] refused -- %s.\n",
335                                   key_name, keyname, valuename,
336                                   win_errstr(result)));
337                         status = werror_to_ntstatus(result);
338                         break;
339                 }
340         }
341
342         status = NT_STATUS_OK;
343  done:
344
345         return status;
346 }
347
348 NTSTATUS printing_tdb_migrate_secdesc(TALLOC_CTX *mem_ctx,
349                                       struct rpc_pipe_client *winreg_pipe,
350                                       const char *key_name,
351                                       unsigned char *data,
352                                       size_t length)
353 {
354         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
355         enum ndr_err_code ndr_err;
356         struct sec_desc_buf secdesc_ctr;
357         DATA_BLOB blob;
358         WERROR result;
359
360         if (strequal(key_name, "printers")) {
361                 return NT_STATUS_OK;
362         }
363
364         blob = data_blob_const(data, length);
365
366         ZERO_STRUCT(secdesc_ctr);
367
368         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
369                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
370         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
371                 DEBUG(2, ("security descriptor pull failed: %s\n",
372                           ndr_errstr(ndr_err)));
373                 return NT_STATUS_NO_MEMORY;
374         }
375
376         DEBUG(2, ("Migrating Security Descriptor: %s\n", key_name));
377
378         result = winreg_set_printer_secdesc(mem_ctx, b,
379                                             key_name,
380                                             secdesc_ctr.sd);
381         if (!W_ERROR_IS_OK(result)) {
382                 return werror_to_ntstatus(result);
383         }
384
385         return NT_STATUS_OK;
386 }